zoukankan      html  css  js  c++  java
  • 享元模式

        享元模式(Flyweight Pattern),Flyweight在拳击比赛中是最轻量级别--“蝇量级"。享元模式以共享的方式支持大量的细粒度对象。

        享元模式在编辑系统中被大量使用,例如字母a会在许多的地方出现,尽管所出现的位置和字模风格不尽相同,但是都可以共享一个字母a的对象。

         Java中的String是final的,改变String的内容就是一个新的String了。只要是内容相同,多个String对象是可以共享一个String实例的。

         享元模式可以分为单纯享元模式和复合享元模式两种。

         单纯享元模式中,所有享元对象都是可以共享的。下面是单纯享元模式的类图:

         

          核心是FlyweightFactory,采取的是登记的工厂方式,用HashMap存储已经构造的ConcreteFlyweight。调用时先去查看HashMap是否已经存在,已存在则直接调用。不存在时先创建再添加到HashMap中以共享使用。

          Flyweight接口的示例代码:    

    public abstract  class Flyweight{
        public abstract  void operation(String state);
    }

          具体类ConcreteFlyweight的示例代码:

    public class ConcreteFlyweight extends Flyweight{
        private Character intrinsicState = null;
    
        public ConcreteFlyweight(Character state){ 
           this.intrinsicState = state;
        }
        
        public void operation(String state){ 
         System.out.print( "
    Intrinsic State = " + intrinsicState +
                ", Extrinsic State = " + state);
        }
    }

            工厂类FlyweightFactory的示例代码:

    public class FlyweightFactory{
        private HashMap flies = new HashMap();
        private Flyweight lnkFlyweight;
        public FlyweightFactory(){
        }
        
        public synchronized Flyweight factory(Character state){ 
        if (flies.containsKey(state)){
                return (Flyweight)flies.get(state);
        }
        else{
                Flyweight fly = new ConcreteFlyweight(state);
                flies.put(state, fly);
                return fly;
            }
        }
        
        public void checkFlyweight(){ 
        Flyweight fly ;
            int i = 0;
    
            System.out.println("
    ==========checkFlyweight()=============");
        for (Iterator it = flies.entrySet().iterator() ; it.hasNext(); ){
            Map.Entry e = (Map.Entry) it.next();
                System.out.println("Item " + (++i) + " : " + e.getKey());
            }
            System.out.println("==========checkFlyweight()=============");
       }
    }

          客户端client的示例代码:

    public class Client{
        private static FlyweightFactory factory;
    
        public static  void main(String[] args){ 
        factory = new FlyweightFactory();
    
        Flyweight fly = factory.factory(new Character('a'));
        fly.operation("First Call");
            
        fly = factory.factory(new Character('b'));
        fly.operation("Second Call");
            
        fly = factory.factory(new Character('a'));
        fly.operation("Third Call");
            
        // intrinsic Flyweight
        factory.checkFlyweight();
       } 
    }

           客户端client在创建2个对象”a”时实际上是共享了一个对象。

           复合享元模式的类图如下所示:

           

          共享的不再是单纯的对象,而是由合成模式合成的复杂对象。类图中的Flyweight,ConcreteFlyweight和ConcreteCompositeFlyweight就构成了合成模式。ConcreteCompositeFlyweight中可以包含ConcreteFlyweight,从而合成更为复杂的对象。

          和单纯享元模式相比较,变化较大是FlyweightFactory和ConcreteCompositeFlyweight。

          下面是FlyweightFactory的实例代码。 加入了一个factory(String compositeState) ,compositeState的每个字符被作为一个ConcreteFlyweight加入到ConcreteCompositeFlyweight中。实际应用中compositeState应该是Vector<Object>。

    public class FlyweightFactory{
    
        private HashMap flies = new HashMap();
        private Flyweight lnkFlyweight;
    
        public FlyweightFactory(){}
    
        public Flyweight factory(String compositeState){ 
           ConcreteCompositeFlyweight compositeFly = new ConcreteCompositeFlyweight();        
           int length = compositeState.length();
           Character state = null;
    
           for(int i = 0; i < length; i++){ 
             state = new Character(compositeState.charAt(i) );
             System.out.println("factory(" + state + ")");
             compositeFly.add(state, this.factory( state) );
           }
           return compositeFly;
        }
    
        public Flyweight factory(Character state){ 
        if ( flies.containsKey(state)){
                return (Flyweight) flies.get( state );
            }
            else{
            Flyweight fly = new ConcreteFlyweight( state );
                flies.put( state , fly);
                return fly;
            }
        }
        
        public void checkFlyweight(){ 
            Flyweight fly ;
            int i = 0 ;
    
            System.out.println("
    ==========checkFlyweight()=============");
            for ( Iterator it = flies.entrySet().iterator() ; it.hasNext(); ){
                Map.Entry e = (Map.Entry) it.next();
                System.out.println( "Item " + (++i) + " : " + e.getKey());
            }
            System.out.println("
    ==========checkFlyweight()=============");
         }
    }

          ConcreteCompositeFlyweight的示例代码为:

    public class ConcreteCompositeFlyweight extends Flyweight {
        private HashMap flies = new HashMap(10);
    
        private Flyweight flyweight;
    
        public ConcreteCompositeFlyweight(){ 
        }
        
        public void add(Character key, Flyweight fly){ 
        flies.put(key, fly);
        }
        
        public void operation(String extrinsicState){
            Flyweight fly =  null;
    
        for (Iterator it = flies.entrySet().iterator();it.hasNext();){
            Map.Entry e = (Map.Entry) it.next();
                fly = (Flyweight) e.getValue();
                fly.operation(extrinsicState);
            }
        }
    }

            一个咖啡摊的例子,咖啡摊虽然每天卖出的咖啡数量很多,但是咖啡的种类是固定且有限的,这里享元模式就很适用。类图如下:

            

          单纯享元模式就很合适,Order充当了抽象接口,Flavor是具体的实现,FlavorFactory采用的是登记的工厂模式。

          订单的代码:

    public abstract class Order{  
        public abstract void serve();
        public abstract String getFlavor();
    }

          咖啡的代码:

    public class Flavor extends Order{  
        private String flavor;    
        public Flavor(String flavor){
            this.flavor = flavor;
        }
        
        public String getFlavor(){
            return this.flavor;
        }
        
        public void serve(){
            System.out.println("Serving flavor " + flavor );
        }
    }

          工厂类的代码;

    public class FlavorFactory{  
        private Order[] flavors = new Flavor[10];
        private int ordersMade = 0;
        private int totalFlavors = 0 ;
        
        public Order getOrder(String flavorToGet){
          if (ordersMade > 0){
             for (int i = 0; i < ordersMade; i++){
                  if (flavorToGet.equals((flavors[i]).getFlavor())){
                        return flavors[i];
                  }
              }
          }
          flavors[ordersMade] = new Flavor(flavorToGet);
          totalFlavors++;
          return flavors[ordersMade++];
       }
        
       public int getTotalFlavorsMade(){
         return totalFlavors;
       }
    }

          客户端的代码:

    public class Client{
        
         private static Order[] flavors = new Flavor[100];
         private static int ordersMade = 0;
         private static FlavorFactory flavorFactory;
         
         private static void takeOrders(String aFlavor){
             flavors[ordersMade++] = flavorFactory.getOrder(aFlavor);
         }
         
         public static void main(String[] args) {
            flavorFactory = new FlavorFactory();
            
            takeOrders("Black Coffee");
            takeOrders("Capucino");
            takeOrders("Espresso");
            takeOrders("Espresso");
            takeOrders("Capucino");
            takeOrders("Capucino");
            takeOrders("Black Coffee");
            takeOrders("Espresso");
            takeOrders("Capucino");
            takeOrders("Black Coffee");
            takeOrders("Espresso");
    
         for (int i = 0; i < ordersMade; i++){
             flavors[i].serve();
         }
    
         System.out.println("
    Total teaFlavor objects made: " +
                flavorFactory.getTotalFlavorsMade());
        }
    }

        从flavorFactory.getTotalFlavorsMade()的结果可以看出,工厂类中登记的咖啡种类只哟3种。

           

  • 相关阅读:
    MOOK学习
    寒假学习计划
    三位影响深刻的老师
    软工第三次作业-结对作业
    2018软工实践第二次作业
    2018软工实践第一次作业
    简单的自我介绍
    福大软工1816 · 第一次作业
    课程作业八
    课程作业七
  • 原文地址:https://www.cnblogs.com/lnlvinso/p/3952483.html
Copyright © 2011-2022 走看看