享元模式

1.定義

用來盡可能減少內(nèi)存使用量,適用于可能存在大量重復(fù)對象的場景梅誓,來緩存可共享的對象桨螺。避免創(chuàng)建過多的對象宾符。
使用共享對象可有效地支持大量的細粒度的對象。

應(yīng)用場景:如果項目中有很多完全相同或相似的對象灭翔,則可以使用享元模式魏烫,節(jié)省內(nèi)存。

核心
享元對象能做到共享的關(guān)鍵就是區(qū)分了內(nèi)部狀態(tài)和外部狀態(tài)肝箱。

  • 內(nèi)部狀態(tài):可以共享哄褒,不會隨環(huán)境變化而變化
  • 外部狀態(tài):不可以共享,會隨環(huán)境變化而變化
享元模式.png

例子:
火車購票系統(tǒng)煌张,很多客戶端不斷訪問服務(wù)器呐赡,服務(wù)器去查詢數(shù)據(jù)庫,然后返回給客戶端骏融;如果每次查詢結(jié)果都用創(chuàng)建的形式链嘀,
那么必將創(chuàng)建大量的對象;比如A-B城市档玻,就那么幾趟車怀泊,座位也就幾種;如果將這些數(shù)據(jù)緩存起來误趴,就不用每次都創(chuàng)建了霹琼。
當(dāng)數(shù)據(jù)庫查詢之后,先從緩存中取凉当,如果沒有在創(chuàng)建對象碧囊。

2.角色

  • FlyweightFactory(享元工廠類):創(chuàng)建并管理享元對象,享元池一般設(shè)計成鍵值對

  • FlyWeight(抽象享元類):通常是一個接口或者抽象類纤怒,聲明公共方法,這些方法可以向外界提供對象的內(nèi)部狀態(tài)天通,設(shè)置外部狀態(tài)泊窘。

  • ConcreteFlyWeight(具體享元類):為內(nèi)部狀態(tài)提供成員變量進行存儲

  • UnsharedConcreteFlyWeight(非共享享元類):不能被共享的子類可以設(shè)計為非共享享元類

3.代碼實現(xiàn)

例如:圍棋中的享元模式,在圍棋中,所有的白色或黑色的(形狀烘豹、大小瓜贾,顏色都一樣)只是位置不同,那像這樣的情況携悯,可以使用享元模式祭芦。
把顏色、形狀憔鬼、大小給共享出來(內(nèi)部狀態(tài))龟劲。位置不共享(外部狀態(tài))

享元模式例子.png

FlyWeight(抽象享元類)

/**
 * 享元類接口:可以共享的有顏色,大小轴或,形狀
 * FlyWeight(抽象享元類):通常是一個接口或者抽象類昌跌,聲明公共方法,
 * 這些方法可以向外界提供對象的內(nèi)部狀態(tài)照雁,設(shè)置外部狀態(tài)蚕愤。
 */
public interface ChessFlyWeight {
    //這里只設(shè)置一個顏色,大小和形狀省略
    void setColor(String c);
    String getColor();
    void display(Coordinate c);//顯示棋子
}

ConcreteFlyWeight(具體享元類):為內(nèi)部狀態(tài)提供成員變量進行存儲

//享元的具體實現(xiàn):ConcreteFlyWeight(具體享元類):為內(nèi)部狀態(tài)提供成員變量進行存儲
class concreteFlyWeight implements ChessFlyWeight{
    private String color;//這里就是為內(nèi)部狀態(tài)提供成員變量進行存儲
    //構(gòu)造的時候初始化color屬性
    public concreteFlyWeight(String color) {
        super();
        this.color = color;
    }
    @Override
    public void setColor(String c) {
        this.color = c;
    }
    @Override
    public String getColor() {
        return color;
    }
    @Override
    public void display(Coordinate c) {
        System.out.println("棋子顏色:"+color);
        System.out.println("棋子位置:("+c.getX()+","+c.getY()+")");
    }
}

UnsharedConcreteFlyWeight(非共享享元類):不能被共享的子類可以設(shè)計為非共享享元類

/**
 * 坐標(biāo)類(外部狀態(tài)):棋子位置
 * UnsharedConcreteFlyWeight(非共享享元類):不能被共享的子類可以設(shè)計為非共享享元類
 */
public class Coordinate {
    private int x,y;//坐標(biāo)位置
    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;
    }
}

FlyweightFactory(享元工廠類)

/**
 * 享元工廠
 * FlyweightFactory(享元工廠類):創(chuàng)建并管理享元對象,享元池一般設(shè)計成鍵值對
 */
public class ChessFlyWeightFactory {
    //享元池:存放享元對象
    private static Map<String,ChessFlyWeight> map = new HashMap<String,ChessFlyWeight>();
    //提供一個享元工廠:創(chuàng)建和管理棋子
    public static ChessFlyWeight getChess(String color){
        if (map.get(color) != null ) {
            return map.get(color);
        }else{
            ChessFlyWeight chess = new concreteFlyWeight(color);
            map.put(color, chess);
            return chess;
        }
    }  
}

客戶端

public static void main(String[] args) {
    ChessFlyWeight chess1 = ChessFlyWeightFactory.getChess("黑色");//黑1
    ChessFlyWeight chess2 = ChessFlyWeightFactory.getChess("黑色");//黑2
    System.out.println(chess1==chess2);//結(jié)果為true饺蚊,相同或相似對象內(nèi)存中只存在一份
      
    //使用享元的外部狀態(tài)
    chess1.display(new Coordinate(10, 10));//黑1在10,10的位置
    chess2.display(new Coordinate(20, 20));//黑2在20,20的位置
      
}

輸出結(jié)果

true

棋子顏色:黑色

棋子位置:(10,10)

棋子顏色:黑色

棋子位置:(20,20)

4.總結(jié)

應(yīng)用場景

比如線程池萍诱,數(shù)據(jù)庫連接池,這些都利用享元模式共享了部分屬性污呼,在池中操作裕坊。

String類的設(shè)計也是享元模式

優(yōu)點:

  • 1.極大的減少內(nèi)存中對象的數(shù)量

  • 2.相同或相似對象內(nèi)存中只存在一份,極大的節(jié)約資源曙求,提高系統(tǒng)性能

  • 3.外部狀態(tài)相對獨立碍庵,不影響內(nèi)部狀態(tài)

缺點:

  • 1.模式較復(fù)雜,使程序邏輯復(fù)雜化

  • 2.為了節(jié)省內(nèi)存悟狱,共享了內(nèi)部狀態(tài)静浴,分離出外部狀態(tài),而讀取外部狀態(tài)使運行時間變長挤渐。

5.Android中

android handler的消息隊列中消息的不斷創(chuàng)建苹享、更新、銷毀浴麻,可以利用享元模式得问;

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市软免,隨后出現(xiàn)的幾起案子宫纬,更是在濱河造成了極大的恐慌,老刑警劉巖膏萧,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件漓骚,死亡現(xiàn)場離奇詭異蝌衔,居然都是意外死亡,警方通過查閱死者的電腦和手機蝌蹂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門噩斟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人孤个,你說我怎么就攤上這事剃允。” “怎么了齐鲤?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵斥废,是天一觀的道長。 經(jīng)常有香客問我佳遂,道長营袜,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任丑罪,我火速辦了婚禮荚板,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘吩屹。我一直安慰自己跪另,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布煤搜。 她就那樣靜靜地躺著免绿,像睡著了一般。 火紅的嫁衣襯著肌膚如雪擦盾。 梳的紋絲不亂的頭發(fā)上嘲驾,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天,我揣著相機與錄音迹卢,去河邊找鬼辽故。 笑死,一個胖子當(dāng)著我的面吹牛腐碱,可吹牛的內(nèi)容都是我干的誊垢。 我是一名探鬼主播,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼症见,長吁一口氣:“原來是場噩夢啊……” “哼喂走!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起谋作,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤芋肠,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后遵蚜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體业栅,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡秒咐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了碘裕。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡攒钳,死狀恐怖帮孔,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情不撑,我是刑警寧澤文兢,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站焕檬,受9級特大地震影響姆坚,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜实愚,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一兼呵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧腊敲,春花似錦击喂、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至没宾,卻和暖如春凌彬,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背循衰。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工铲敛, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人羹蚣。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓原探,卻偏偏與公主長得像,于是被迫代替她去往敵國和親顽素。 傳聞我的和親對象是個殘疾皇子恶导,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容