以共享的方式高效的支持大量的細粒度對象。享元對象之內蘊和外蘊狀態達到對象共享。編輯器
存儲在享元對象內部,不會隨環境的改變而改變。由於其不可變,因此內蘊狀態是能夠共享的。內蘊狀態在對象建立後就不會改變。ide
會隨着環境的改變而改變,不可共享。由客戶端保存外蘊狀態,在須要使用的時候傳入享元對象內部。
this
全部具體享元類的超類。規定出公共接口。須要外蘊狀態的操做能夠經過參數形式傳入。spa
實現抽象享元角色規定的接口。若是有內蘊狀態,必須負責爲內蘊狀態低筒存儲空間,且與對象所處的周圍環境無關。code
負責建立和管理享元角色。必須保證享元對象能夠被系統適當的共享。客戶端調用一個享元對象時,享元工廠角色會檢查系統是否已有符合要求的享元角色。有則返回,無則建立。對象
維護全部享元對象的引用。自行存儲全部享元對象的外蘊狀態。blog
抽象享元角色:接口
/** * 抽象享元角色 */ 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複合享元模式
全部具體享元類的超類。規定出公共接口。須要外蘊狀態的操做能夠經過參數形式傳入。
實現抽象享元角色規定的接口。若是有內蘊狀態,必須負責爲內蘊狀態低筒存儲空間,且與對象所處的周圍環境無關。
不可共享。能夠分解爲多個單純享元角色組合。
負責建立和管理享元角色。必須保證享元對象能夠被系統適當的共享。客戶端調用一個享元對象時,享元工廠角色會檢查系統是否已有符合要求的享元角色。有則返回,無則建立。
維護全部享元對象的引用。自行存儲全部享元對象的外蘊狀態。
抽象享元角色:
/** * 抽象享元角色 */ 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與模式》