再戰設計模式(十一)之享元模式
阿新 • • 發佈:2019-05-14
getc mage pub 維護 pan 模式 har 創建 vat
享元模式
場景:
內存屬於稀缺資源,不要隨便浪費。如果有很多個完全相同或相似的 對象,我們可以通過享元模式,節省內存.
核心:
本質:享元模式以共享的方式高效地支持大量細粒度對象的重用 享元對象能做到共享的關鍵是區分了內部狀態和外部狀態 內部狀態:可以共享,不會隨環境變化而改變 外部狀態:不可以共享,會隨環境變化而改變 現在有個需求,需要為圍棋設置一個程序,那麽圍棋的棋子改如何設計?總共有很多黑子和白子,難道我們需要為每一個棋子生成一個對象嗎?
顯然這樣的設計是不合理的.這個時候我們就可以用到享元模式!
類圖:如下
類圖的看比較復雜.我們來剖析下 chessFlyWeight:是一個接口,聲明了一些公共的方法,這些方法可以向外提供內部狀態,以及設置外部的狀態 ChessFlyWeightImpl: 是一個享元對象的實例,可以存儲內部狀態(因為可以共享) ,可以獲取外部狀態的屬性.如 x y ChessCoordinateConcrete: 是享元對象的外部狀態不可以共享,,可以隨意設置 ChessFlyWeightFactory : 就是通過內部狀態.獲取對象..就像我們平時用的緩存一樣.我把他設置成單例的了. client: 可以具體的調用這裏就不多說了.
代碼:
/** * 享元類 * @Created by xiaodao */ public interface ChessFlyWeight { void setColor(String color ); String getColor(); void display(ChessCoordinateConcrete c ); } /** * 為內部對象,提供享元存儲.!! * @Created by xiaodao */ public class ChessFlyWeightImpl implements ChessFlyWeight {private String color; public ChessFlyWeightImpl(String color) { this.color = color; } public void setColor(String color) { this.color = color; } public String getColor() { return this.color; } public void display(ChessCoordinateConcrete c) { System.out.println("chess‘s color = "+ color); System.out.println("chess;s position x = "+ c.getX() +"----- y = "+ c.getY()); } } /** * 不可共享的外部結構 * @Created by xiaodao */ public class ChessCoordinateConcrete { private int x,y; public ChessCoordinateConcrete(int x, int y) { this.x = x; this.y = y; } public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } public void setY(int y) { this.y = y; } } /** * 享元 工廠 返回 接口... * @Created by xiaodao */ public class ChessFlyWeightFactory { private static ChessFlyWeightFactory instance= new ChessFlyWeightFactory(); private static HashMap<String,ChessFlyWeight> map = new HashMap<String, ChessFlyWeight>(); public ChessFlyWeight getChess(String color){ if(map.get(color) !=null){ return map.get(color); }else{ ChessFlyWeight chessFlyWeight = new ChessFlyWeightImpl(color); map.put(color,chessFlyWeight); return map.get(color); } } private ChessFlyWeightFactory() { } public static ChessFlyWeightFactory getInstance(){ return instance; } }
/** * @Created by xiaodao */ public class Client { public static void main(String[] args) { ChessFlyWeightFactory c = ChessFlyWeightFactory.getInstance(); ChessFlyWeight chess1 = c.getChess("黑色"); chess1.display(new ChessCoordinateConcrete(10,20)); ChessFlyWeight chess2 = c.getChess("黑色"); System.out.println("-----------------"); chess2.display(new ChessCoordinateConcrete(20,30)); System.out.println(chess1); System.out.println(chess2); } } 獲取到的結果: chess‘s color = 黑色 chess;s position x = 10----- y = 20 ----------------- chess‘s color = 黑色 chess;s position x = 20----- y = 30 [email protected] [email protected]
這樣的運行之後..我們就可以獲取到同一個對象,但是他的外部不可共享的屬性確不一樣..這就可以節省很多內存空間.
角色:
享元模式實現:
– FlyweightFactory享元工廠類
• 創建並管理享元對象,享元池一般設計成鍵值對
– FlyWeight抽象享元類
• 通常是一個接口或抽象類,聲明公共方法,這些方法可以向外界提供對象 的內部狀態,設置外部狀態。
– ConcreteFlyWeight具體享元類
• 為內部狀態提供成員變量進行存儲
– UnsharedConcreteFlyWeight非共享享元類
• 不能被共享的子類可以設計為非共享享元類
總結:
享元模式,我們在工作中很少用,寫起來比較復雜.維護也不好維護,但是我們還是需要了解,這樣對閱讀源碼是比較友好的.
優點:
- 極大的減少了內存中的對象數量
- 相同或者相似的對象內存中只有一份,節省空間
- 外部狀態相對獨立,不影響內部的屬性
缺點:
- 模式比較復雜.看上面的類圖就知道,感覺不夠清晰,是程序邏輯復雜化
- 為了使對象可以共享,享元模式需要將享元對象的狀態外部化,而讀取外部狀態使得運行時間變長。 用時間換取了空間
JDK或者項目中的使用
string 也是使用的享元模式,共享常量池.
integer: 中也使用了
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
Integer a = Integer.valueOf(100); Integer b = 100; Integer c =Integer.valueOf(1000); Integer d = Integer.valueOf(1000); System.out.println(a==b); System.out.println(c==d);
true
false
integer 最小是-128 最大是127 在緩存中,當然也可以設置.也是使用的享元模式
數據連接池還有各種pool 也是使用的這個模式
再戰設計模式(十一)之享元模式