內存屬於稀缺資源,不要隨便浪費。若是有不少個徹底相同或類似的對象,能夠經過享元模式,節省內存。java
享元模式核心:數據庫
(1)享元模式能夠共享的、方式高效的支持大量細粒度對象的重用; ide
(2)享元對象能作到共享的關鍵是區分了內部狀態和外部狀態:性能
① 內部狀態:能夠共享,不會隨環境變化而改變測試
② 外部狀態:不能共享,會隨環境變化而改變this
(1)FlyWeightFactory享元工廠類spa
建立並管理享元對象,享元池通常設計成鍵值對。線程
(2)FlyWeight抽象享元類設計
一般是一個接口,聲明公共方法,這些方法能夠向外界提供對象的內部狀態,設置外部狀態。3d
(3)ConcreteFlyWeight具體享元類
內部狀態提供成員變量進行存儲。
(4)UnShareConcreteFlyWeight非共享享元類
不能被共享的子類能夠設計成非共享享元類。
場景:圍棋中每個棋子都是一個對象。棋子有以下屬性:
顏色 狀態 大小(這些是能夠共享的)稱之爲:內部狀態
位置(這是不能夠共享的)稱之爲:外部狀態
1 /** 2 * 抽象享元類FlyWeight 3 * @author CL 4 * 5 */ 6 public interface ChessFlyWeight { 7 void setColor(String color); 8 String getColor(); 9 void display(Coordinate c); 10 } 11 12 /** 13 * ConcreteFlyWeight具體享元類 14 * 內部狀態 15 * @author CL 16 * 17 */ 18 class ConcreteChess implements ChessFlyWeight { 19 20 private String color; 21 22 public ConcreteChess(String color) { 23 this.color = color; 24 } 25 26 @Override 27 public void setColor(String color) { 28 this.color = color; 29 } 30 31 @Override 32 public String getColor() { 33 return color; 34 } 35 36 @Override 37 public void display(Coordinate c) { 38 System.out.println("棋子的顏色: "+color); 39 System.out.println("棋子的位置: ["+c.getX()+","+c.getY()+"]"); 40 } 41 42 }
1 import java.util.HashMap; 2 import java.util.Map; 3 4 /** 5 * 享元工廠類 6 * @author CL 7 * 8 */ 9 public class ChessFlyWeightFactory { 10 //享元池 11 private static Map<String, ChessFlyWeight> map = 12 new HashMap<String, ChessFlyWeight>();; 13 14 public static ChessFlyWeight getChess(String color) { 15 if (map.get(color) != null) { 16 return map.get(color); 17 } else { 18 ChessFlyWeight cfw = new ConcreteChess(color); 19 map.put(color, cfw); 20 return cfw; 21 } 22 } 23 24 }
1 /** 2 * 外部狀態 3 * UnShareFlyWeight非共享享元類 4 * @author CL 5 * 6 */ 7 public class Coordinate { 8 private int x, y; 9 10 public Coordinate(int x, int y) { 11 this.x = x; 12 this.y = y; 13 } 14 15 public int getX() { 16 return x; 17 } 18 19 public void setX(int x) { 20 this.x = x; 21 } 22 23 public int getY() { 24 return y; 25 } 26 27 public void setY(int y) { 28 this.y = y; 29 } 30 }
測試:
1 /** 2 * 測試享元模式 3 * @author CL 4 * 5 */ 6 public class Client { 7 8 public static void main(String[] args) { 9 ChessFlyWeight c1 = ChessFlyWeightFactory.getChess("黑色"); 10 ChessFlyWeight c2 = ChessFlyWeightFactory.getChess("黑色"); 11 System.out.println(c1); 12 System.out.println(c2); //c1 和 c2 是同一對象 13 14 System.out.println("--------------------"); 15 c1.display(new Coordinate(10, 10)); 16 c2.display(new Coordinate(20, 20)); 17 } 18 19 }
控制檯輸出:
com.caolei.flyweight.ConcreteChess@759ebb3d com.caolei.flyweight.ConcreteChess@759ebb3d -------------------- 棋子的顏色: 黑色 棋子的位置: [10,10] 棋子的顏色: 黑色 棋子的位置: [20,20]
優勢:
(1)極大的減小內存中對象的數量;
(2)相同或類似對象內存中只存一份,極大的節約資源,提升系統性能;
(3)外部狀態相對獨立,不影響內部狀態。
缺點:
(1)模式較複雜,使程序邏輯複雜化;
(2)爲了節省內存,共享了內部狀態,分離出外部狀態,而讀取外部狀態使運行時間較長,用時間換空間。
(1)享元模式因爲其共享的特性,能夠在任何「池」中操做,好比:線程池、數據庫鏈接池;
(2)String類的設計也是享元模式;
(3)…………