1、適用場景java
內存屬於稀缺資源,不能隨意浪費。若是在一個系統中有不少個徹底相同或類似的對象,咱們就可使用享元模式,讓他們共享一分內存便可,沒必要每一個都去實例化對象,從而節省內存空間。架構
2、模式核心性能
享元模式以共享的方式高效的支持大量細粒度對象的重用。
享元對象能作到共享的關鍵是區分了內部狀態和外部狀態。
內部狀態:能夠共享,不會隨環境改變而改變。
外部狀態:不能夠共享,會隨環境改變而改變。this
圍棋例子:
spa
每個圍棋棋子都是一個對象,並都有以下屬性:
架構設計
3、享元模式結構設計
UM類圖:
code
FlyWeight抽象享元類:一般是一個接口或抽象類,聲明公共方法,這些方法能夠向外界提供對象的內部狀態,設置外部狀態。對象
UnsharedConcreteFlyWeight非共享享元類:不能被共享的子類能夠設計爲非共享享元類。接口
ConcreteFlyWeight具體享元類:爲內部狀態提供成員變量進行存儲。
FlyWeightFactory享元工廠類:建立並管理享元對象,享元池通常設計爲鍵值對。
圍棋代碼示例:
FlyWeight抽象享元類:
public interface ChessFlyWeight { String getColor();//獲取顏色,內部狀態 void display(Coordinate c);//展現位置,外部狀態 }
UnSharedConcreteFlyweight 非共享享元類:
/** * 外部狀態:棋子座標位置 */ public class Coordinate { private int x,y; public Coordinate(int x, int y) { super(); 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; } }
ConcreteFlyWeight具體享元類:
class ConcreteChess implements ChessFlyWeight{ private String color; public ConcreteChess(String color) { super(); this.color = color; } public String getColor() { return color; } public void display(Coordinate c) { System.out.println("棋子顏色:"+color); System.out.println("棋子位置"+c.getX()+"-----"+c.getY()); } }
FlyWeightFactory享元工廠
public class ChessFlyWeightFactory { //享元池 private static Map<String,ChessFlyWeight> map=new HashMap<String,ChessFlyWeight>(); public static ChessFlyWeight getChess(String color){ if(map.get(color)!=null){ return map.get(color); }else{ ChessFlyWeight cfw=new ConcreteChess(color); map.put(color, cfw); return cfw; } } }
客戶端
public class Client { public static void main(String[] args) { ChessFlyWeight chess1=ChessFlyWeightFactory.getChess("黑色"); ChessFlyWeight chess2=ChessFlyWeightFactory.getChess("黑色"); System.out.println(chess1); System.out.println(chess2); System.out.println("-----增長外部狀態的處理----"); chess1.display(new Coordinate(10,10)); chess2.display(new Coordinate(20,20)); } } //輸出結果 flyweight.ConcreteChess@15db9742 flyweight.ConcreteChess@15db9742 -----增長外部狀態---- 棋子顏色:黑色 棋子位置10-----10 棋子顏色:黑色 棋子位置20-----20
從上面的輸出結果可看出chess1,chess2兩個對象使用的是同一個內存空間,即它們是同一實例。
在JAVA語言中,String類型就是使用了享元模式。String對象是final類型,對象一旦建立就不可改變。在JAVA中字符串常量都是存在常量池中的,JAVA會確保一個字符串常量在常量池中只有一個拷貝。String a=」abc」,其中」abc」就是一個字符串常量。
4、總結
優勢:
極大減小內存中對象的數量。
相同或類似的對象內存只保持一份,極大的節約資源,提升系統性能。
外部狀態相對獨立,不影響內部變化。
缺點:
模式較複雜,使程序邏輯複雜化。
爲了節省內存,共享了內部狀態,分離出了外部狀態,而讀取外部狀態使運行時間變長。用時間換空間。
分享
本人13年Java開發經驗及產品研發經驗,BAT背景,曾在多家知名企業擔任技術總監、企業方案選型首席顧問,前後從事內核開發、大型Java系統架構設計和物聯網系統架構設計開發,精通複雜業務技術方案選型、架構、核心難點攻關,對於java語言及項目有很是深刻的理解和豐富的實操經驗,熱愛前沿技術,樂於進行技術分享與技術探討。