享元模式

享元模式

       以共享的方式高效的支持大量的細粒度對象。享元對象之內蘊和外蘊狀態達到對象共享。編輯器

      

1.1內蘊狀態  

       存儲在享元對象內部,不會隨環境的改變而改變。由於其不可變,因此內蘊狀態是能夠共享的。內蘊狀態在對象建立後就不會改變。ide

1.2外蘊狀態

       會隨着環境的改變而改變,不可共享。由客戶端保存外蘊狀態,在須要使用的時候傳入享元對象內部。

this

2.1單純享元模式

2.1.1結構:

  • 抽象享元角色:

  全部具體享元類的超類。規定出公共接口。須要外蘊狀態的操做能夠經過參數形式傳入。spa

  • 具體享元角色(ConcreteFlyweight):

  實現抽象享元角色規定的接口。若是有內蘊狀態,必須負責爲內蘊狀態低筒存儲空間,且與對象所處的周圍環境無關。code

  • 享元工廠角色(FlyweightFactory):

  負責建立和管理享元角色。必須保證享元對象能夠被系統適當的共享。客戶端調用一個享元對象時,享元工廠角色會檢查系統是否已有符合要求的享元角色。有則返回,無則建立。對象

  • 客戶端角色(Client):

  維護全部享元對象的引用。自行存儲全部享元對象的外蘊狀態。blog

 

2.1.2代碼

抽象享元角色:接口

/**
 * 抽象享元角色
 */
public interface Flyweight {
    void operate(String outerState);
}

 

具體享元角色: 內存

/**
 * 具體享元角色
 */
public class ConcreteFlyweight implements Flyweight{
    private String innerState = null;

    /**
     * 經過構造器初始化內蘊狀態
     * 因爲客戶端不能直接初始化具體享元對象,因此這裏的構造器能夠設爲私有的,
     *    而後經過一個初始化方法進行內蘊狀態的初始化
     */
    public ConcreteFlyweight(String innerState) {
        this.innerState = innerState;
    }

    @Override
    public void operate(String outerState) {
        System.out.println("外蘊狀態:" + outerState + ";內蘊狀態:" + innerState);
    }
}

 

享元工廠: get

/**
 * 享元工廠角色
 */
public class FlyweightFactory {
    private Map<String, Flyweight> files = new HashMap<>();

    public FlyweightFactory() {
    }

    public Flyweight factory(String innerState){
        if(files.containsKey(innerState)){
            return files.get(innerState);
        }else{
            Flyweight flyweight = new ConcreteFlyweight(innerState);
            files.put(innerState, flyweight);
            return flyweight;
        }
    }

    public void printAll(){
        System.out.println(new Gson().toJson(files));
    }
}


客戶端: 

/**
 * 客戶端
 */
public class Client {
    public static void main(String[] args) {
        FlyweightFactory factory = new FlyweightFactory();
        Flyweight flyweight = factory.factory("內蘊狀態1");
        flyweight.operate("外蘊狀態1");

        flyweight = factory.factory("內蘊狀態2");
        flyweight.operate("外蘊狀態2");

        flyweight = factory.factory("內蘊狀態1");
        flyweight.operate("外蘊狀態3");

        factory.printAll();
    }
}

 

2.2複合享元模式 

2.2.1結構:

  • 抽象享元角色:

  全部具體享元類的超類。規定出公共接口。須要外蘊狀態的操做能夠經過參數形式傳入。

  • 具體享元角色(ConcreteFlyweight):

  實現抽象享元角色規定的接口。若是有內蘊狀態,必須負責爲內蘊狀態低筒存儲空間,且與對象所處的周圍環境無關。

  • 複合享元角色(UnsharableFlyweight)

  不可共享。能夠分解爲多個單純享元角色組合。

  • 享元工廠角色(FlyweightFactory):

  負責建立和管理享元角色。必須保證享元對象能夠被系統適當的共享。客戶端調用一個享元對象時,享元工廠角色會檢查系統是否已有符合要求的享元角色。有則返回,無則建立。

  • 客戶端角色(Client):

  維護全部享元對象的引用。自行存儲全部享元對象的外蘊狀態。

 

 

2.2.2代碼:

抽象享元角色:

/**
 * 抽象享元角色
 */
public interface Flyweight {
    void operate(String outerState);
}

 

具體享元角色: 

/**
 * 具體享元角色
 */
public class ConcreteFlyweight implements Flyweight {
    private String innerState = null;

    /**
     * 經過構造器初始化內蘊狀態
     * 因爲客戶端不能直接初始化具體享元對象,因此這裏的構造器能夠設爲私有的,
     *    而後經過一個初始化方法進行內蘊狀態的初始化
     */
    public ConcreteFlyweight(String innerState) {
        this.innerState = innerState;
    }

    @Override
    public void operate(String outerState) {
        System.out.println("外蘊狀態:" + outerState + ";內蘊狀態:" + innerState);
    }
}

 

複合享元角色: 

/**
 * 複合享元角色
 */
public class CompositeFlyweight implements Flyweight {
    private Map<String, Flyweight> files = new HashMap<>();

    private Flyweight flyweight;
    @Override
    public void operate(String outerState) {
        Iterator it = files.entrySet().iterator();
        while(it.hasNext()){
            Map.Entry e = (Map.Entry) it.next();
            flyweight = (Flyweight) e.getValue();
            flyweight.operate(outerState);
        }
    }

    public void add(String key, Flyweight flyweight){
        files.put(key, flyweight);
    }
}


享元工廠角色: 

/**
 * 享元工廠角色
 */
public class FlyweightFactory {
    private Map<String, Flyweight> files = new HashMap<>();

    public FlyweightFactory() {
    }

    public Flyweight factory(List<String> compositeState){
        CompositeFlyweight compositeFlyweight = new CompositeFlyweight();
        for(String state : compositeState){
            System.out.println("facotry("+ state +")");
            compositeFlyweight.add(state, this.factory(state));
        }
        return compositeFlyweight;
    }
    public Flyweight factory(String innerState){
        if(files.containsKey(innerState)){
            return files.get(innerState);
        }else{
            Flyweight flyweight = new ConcreteFlyweight(innerState);
            files.put(innerState, flyweight);
            return flyweight;
        }
    }

    public void printAll(){
        System.out.println(new Gson().toJson(files));
    }
}


客戶端: 

/**
 * 客戶端
 */
public class Client {
    public static void main(String[] args) {
        FlyweightFactory factory = new FlyweightFactory();
        Flyweight flyweight = factory.factory("內蘊狀態1");
        flyweight.operate("外蘊狀態1");

        flyweight = factory.factory("內蘊狀態2");
        flyweight.operate("外蘊狀態2");

        flyweight = factory.factory("內蘊狀態1");
        flyweight.operate("外蘊狀態3");

        List<String> state = Arrays.asList("內蘊狀態1","內蘊狀態2","內蘊狀態3");
        factory.factory(state);

        factory.printAll();
    }
}


3小結
 

       對象能夠按內蘊狀態分組,即一個內蘊狀態表明一個對象。享元工廠維護了全部享元對象。經過內蘊狀態去獲取一個惟一的享元對象出來。享元對象都必須由享元工廠獲取。享元模式大幅度下降內存中的對象數量。但卻加大了系統的複雜性。在一些特定環境下,享元模式是個大殺器。如文本編輯器,五子棋。

 

 

 

 

 

參考:

《Java與模式》

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息