GOF23設計模式之享元模式(flyweight)

1、享元模式概述

  內存屬於稀缺資源,不要隨便浪費。若是有不少個徹底相同或類似的對象,能夠經過享元模式,節省內存。java

  享元模式核心:數據庫

    (1)享元模式能夠共享的、方式高效的支持大量細粒度對象的重用; ide

    (2)享元對象能作到共享的關鍵是區分了內部狀態和外部狀態:性能

        ① 內部狀態:能夠共享,不會隨環境變化而改變測試

        ② 外部狀態:不能共享,會隨環境變化而改變this

2、享元模式實現

  (1)FlyWeightFactory享元工廠類spa

      建立並管理享元對象,享元池通常設計成鍵值對。線程

  (2)FlyWeight抽象享元類設計

      一般是一個接口,聲明公共方法,這些方法能夠向外界提供對象的內部狀態,設置外部狀態。3d

  (3)ConcreteFlyWeight具體享元類

      內部狀態提供成員變量進行存儲。

  (4)UnShareConcreteFlyWeight非共享享元類

      不能被共享的子類能夠設計成非共享享元類。

3、元模式場景導入示例代碼

  場景:圍棋中每個棋子都是一個對象。棋子有以下屬性:

       顏色 狀態 大小(這些是能夠共享的)稱之爲:內部狀態

         位置(這是不能夠共享的)稱之爲:外部狀態

 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]

4、享元模式優缺點

  優勢:

    (1)極大的減小內存中對象的數量;

    (2)相同或類似對象內存中只存一份,極大的節約資源,提升系統性能;

    (3)外部狀態相對獨立,不影響內部狀態。

  缺點:

    (1)模式較複雜,使程序邏輯複雜化;

    (2)爲了節省內存,共享了內部狀態,分離出外部狀態,而讀取外部狀態使運行時間較長,用時間換空間。

5、享元模式常見開發應用場景

  (1)享元模式因爲其共享的特性,能夠在任何「池」中操做,好比:線程池、數據庫鏈接池;

  (2)String類的設計也是享元模式;

  (3)…………

相關文章
相關標籤/搜索