設計模式之享元模式

享元模式(FlyWeight),其含義是運用共享技術有效地支持大量細粒度的對象,即系統只使用少許的對象,而這些對象都相近,狀態變化很小,對象使用次數卻不少。java

享元模式能作到共享的關鍵是區份內蘊狀態和外蘊狀態,一個內蘊狀態是存儲在享元對象內部的,而且是不會隨環境改變而有所不一樣的。所以一個享元能夠具備內蘊狀態並能夠共享。一個外蘊狀態是隨環境改變而改變的、不能夠共享的狀態。享元對象的外蘊狀態必須由客戶端保存,並在享元對象被建立以後,在須要使用的時候再傳入到享元對象內部。外蘊狀態不能夠影響享元對象的內蘊對象。換句話說,它們是互相獨立的。ide

其適用性:測試

一個應用程序使用了大量的對象,this

徹底因爲使用大量的對象,形成很大的存儲開銷,spa

對象的大多數狀態均可變爲外部狀態,設計

若是刪除對象的外部狀態,那麼能夠用相對較少的共享對象取代不少組對象,code

應用程序不依賴於對象標識。因爲Flyweight對象能夠被共享,對於概念上明顯有別的對象,標識測試將返回真值。對象

  結構以下:blog

           

  享元模式在使用時分爲單純享元模式和複合享元模式兩種,單純享元模式中Flyweight都是可共享的,也是如今Flyweight實現的較多實例。如今先列出單純享元模式:繼承

 Flyweight.java

package org.designpattern.structural.flyweight;

    public  abstract  class Flyweight {
          protected  Character  intrinsicState;

          protected Flyweight( Character  intrinsicState){
              this.intrinsicState = intrinsicState;
         };
          public  abstract   void  operation(String extrinsicState);
          public  Character  getIntrinsicState(){
              return  this.intrinsicState;
         };
     }

  ConcreteFlyweight.java繼承了Flyweight,實現了一個operation方法,類略。Flyweight是經過工廠獲得的,下面是FlyweightFactory.java

package  org.designpattern.structural.flyweight;
import java.util.HashMap;

public  class FlyweightFactory {
     private HashMap flyWeights;
        public FlyweightFactory(){
         flyWeights =  new HashMap();
    }
     public Flyweight getFlyweight(Character key){
          if( this.flyWeights.containsKey(key)){
            System.out.println(key + " already created!");
             return (Flyweight) flyWeights.get(key);
        } else{
             Flyweight flyweight =  new ConcreteFlyweight(key);
             flyWeights.put(key,flyweight);
              return flyweight;
        }
    }

  若是是單純享元模式,到這裏再加上客戶測試類就結束了。若是使用複合享元模式,複合元素的對象的狀態是會改變的,因此複合享元對象是不能共享的。須要再增長一個類UnsharedConcreteFlyeweight.java

public class UnsharedConcreteFlyweight extends Flyweight {

     private HashMap<Character,Flyweight> unsharedFlyweights;
     private Flyweight  flyweight;

     public UnsharedConcreteFlyweight(Character intrinsicState) {
         super(intrinsicState);
         this.unsharedFlyweights =  new HashMap(20);
    }

     public  void add(Character key,Flyweight flyweight){
         this.unsharedFlyweights.put(key,flyweight);
    }
    @Override
     public  void operation(String extrinsicState) {
        System.out.println("extrinsicState:" + extrinsicState);
        Iterator<Map.Entry<Character,Flyweight>> it = unsharedFlyweights.entrySet().iterator();
         while(it.hasNext()){
            Map.Entry<Character,Flyweight> entry = it.next();
            Flyweight fly = entry.getValue();
            fly.operation(extrinsicState);
        }
    }

   } 

此時在FlyweighFactory.java中須要增長一個方法支持不可共享的Flyweight的調用:

 public Flyweight getUnsharedFlyweight(String keys ){

        UnsharedConcreteFlyweight unsharedConcreteFlyweight =  new UnsharedConcreteFlyweight( null);
         for( int i=0;i<keys.length();i++){
            Character character =  new Character(keys.charAt(i));
            unsharedConcreteFlyweight.add(character,getFlyweight(character));
        }
         return unsharedConcreteFlyweight;

    }

 下面是客戶測試類:

   package  org.designpattern.structural.flyweight;
   public  class Main {
     public  static  void main(String[] args) {
        FlyweightFactory factory =  new FlyweightFactory();
        Flyweight fly1 = factory.getFlyweight('a');
        fly1.operation("First call!");
        Flyweight fly2 = factory.getFlyweight('b');
        fly2.operation("Second call!");
        Flyweight fly3 = factory.getFlyweight('a');
        fly3.operation("Third call!");
        System.out.println(fly1 == fly3);

        Flyweight unsharedFlyweight = factory.getUnsharedFlyweight("abcde");
        unsharedFlyweight.operation("Forth call!");
     }

  } 

 享元模式的有效性很大程度上取決於在何種情景下使用它,其主要缺點是使系統設計變得更加複雜,將享元對象的狀態外部化,而讀取外部狀態使得運行時間稍微變長。咱們一般會把Flyweight工廠設計爲單例模式,其能夠和許多模式共同使用更有效。

相關文章
相關標籤/搜索