Java設(shè)計(jì)模式----享元模式

場(chǎng)景

內(nèi)存屬于稀缺資源,不要隨便浪費(fèi)。如果有很多完全相同或相似的對(duì)象,我們可以通過享元模式,節(jié)省內(nèi)存。

核心

  • 享元模式以共享的方式高效地支持大量細(xì)粒度對(duì)象的重用。
  • 享元對(duì)象能做到共享的關(guān)鍵是區(qū)分了內(nèi)部狀態(tài)和外部狀態(tài)。
    內(nèi)部狀態(tài):可以共享,不會(huì)隨環(huán)境變化而改變
    外部狀態(tài):不可以共享,回隨環(huán)境變化而改變

享元模式實(shí)現(xiàn)

  • FlyweightFactory享元工廠類
    創(chuàng)建并管理享元對(duì)象,享元池一般設(shè)計(jì)成鍵值對(duì)
  • Flyweight抽象享元類
    通常是一個(gè)接口或抽象類,聲明公共方法,這些方法可以向外界提供對(duì)象的內(nèi)部狀態(tài),設(shè)置外部狀態(tài)
  • ConcreteFlyweight具體享元類
    為內(nèi)部狀態(tài)提供成員變量進(jìn)行儲(chǔ)存
  • UnsharedConcreteFlyweight非共享享元類
    不能被共享的子類可以設(shè)計(jì)為非共享享元類


    享元模式
package flyweight;

// 以圍棋為例
// Flyweight
public interface Chess {
    String getColor();
    void display(Coordinate c);
}

// ConcreteFlyweight
class ConcreteChess implements Chess{
    private String color;

    public ConcreteChess(String color) {
        this.color = color;
    }

    public String getColor() {
        return color;
    }

    public void display(Coordinate c) {
        System.out.println("顏色:"+color);
        System.out.println("位置:("+c.getX()+","+c.getY()+")");
    }
}
// UnsharedConcreteFlyweight
public class Coordinate{
    private int x,y;

    public Coordinate(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;
    }
}
package flyweight;

import java.util.HashMap;
import java.util.Map;

// FlyweightFactory
public class ChessFactory {
    private static Map<String,Chess> map = new HashMap<String, Chess>();

    public static Chess getChess(String color){
        if (map.get(color) != null){
            return map.get(color);
        }else{
            Chess chess = new ConcreteChess(color);
            map.put(color,chess);
            return chess;
        }
    }
}
package flyweight;

public class Client {
    public static void main(String[] args) {
        Chess chess = ChessFactory.getChess("黑色");
        Chess chess1 = ChessFactory.getChess("黑色");
        System.out.println(chess);
        System.out.println(chess1);

        System.out.println("=====增加外部狀態(tài)=====");

        chess.display(new Coordinate(10,10));
        chess1.display(new Coordinate(20,20));
    }
}

輸出:
flyweight.ConcreteChess@4edf9252
flyweight.ConcreteChess@4edf9252
=====增加外部狀態(tài)=====
顏色:黑色
位置:(10,10)
顏色:黑色
位置:(20,20)

享元模式開發(fā)中應(yīng)用的場(chǎng)景:

  • 享元模式由于其共享的特性,可以在任何"池"中操作,比如線程池、數(shù)據(jù)庫(kù)連接池。
  • String類的設(shè)計(jì)也是享元模式

優(yōu)點(diǎn)

  • 極大減少內(nèi)存中對(duì)象的數(shù)量
  • 相同或相似對(duì)象內(nèi)存中只存一份,極大節(jié)約資源,提高系統(tǒng)性能
  • 外部狀態(tài)相對(duì)獨(dú)立,不影響內(nèi)部狀態(tài)

缺點(diǎn)

  • 模式較復(fù)雜,是程序邏輯復(fù)雜化
  • 為了節(jié)省內(nèi)存,共享了內(nèi)部狀態(tài),分離出外部狀態(tài),而讀取外部狀態(tài)使運(yùn)行時(shí)間變長(zhǎng)。用時(shí)間換取了空間。

何時(shí)使用

如果一個(gè)應(yīng)用程序使用了大量的對(duì)象,而大量的這些對(duì)象造成了很大的存儲(chǔ)開銷時(shí)就應(yīng)該考慮使用;還有就是對(duì)象的大多數(shù)狀態(tài)可以外部狀態(tài),如果刪除對(duì)象的外部狀態(tài),那么可以用相對(duì)較少的共享對(duì)象取代很多組對(duì)象,此時(shí)可以考慮使用享元模式。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容