享元模式

    享元模式(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( "\nIntrinsic 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("\n==========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("\n==========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("\n==========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("\nTotal teaFlavor objects made: " +
            flavorFactory.getTotalFlavorsMade());
    }
}

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

       

posted on 2014-09-02 22:54  lnlvinso  阅读(199)  评论(0编辑  收藏  举报