Java設計模式11——享元模式

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語言及項目有很是深刻的理解和豐富的實操經驗,熱愛前沿技術,樂於進行技術分享與技術探討。
圖片描述

相關文章
相關標籤/搜索