23種設計模式之享元模式

享元模式是對象池的一種實現,用來儘可能減少內存使用量,它適合用於可能存在大量重複對象的場景,來緩存可共享的對象,達到對象共享,避免創建過多對象的效果,這樣就可以提升性能、避免內存溢出等。
享元對象中的部分狀態是可以共享的,可以共享的狀態稱爲內部狀態,內部狀態不會隨着環境變化,不可共享的狀態則稱爲外部狀態,它們會隨着環境的改變而改變。

享元模式定義
使用共享對象可有效地支持大量的細粒度的對象

使用場景
a. 系統中存在大量的相似對象
b. 細粒度的對象都具備較近的外部狀態,而且內部狀態與環境無關,也就是說對象沒有特定身份。
c. 需要緩衝池的場景

UML類圖

這裏寫圖片描述

角色介紹:
Flyweight:享元對象抽象基類接口。
ConcreteFlyweight:具體的享元對象
FlyweightFactory:享元工廠,負責管理享元對象池和創建享元對象。

源碼示例:
春節搶票回家

// ticket接口
public interface Ticket {
    public void showTicketInfo(String bunk);
}
public class TrainTicket implements Ticket {
    public String from; // 始發地
    public String to; // 目的地
    public String bunk; // 鋪位
    public int price; // 價格

    public TrainTicket(String from, String to) {
        this.from = from;
        this.to = to;
    }

    @Override
    public void showTicketInfo(String bunk) {
        price = new Random().nextInt(300);
        System.out.println("購買 從 " + from + " 到 " + to + "的 " + bunk + "火車票" + ",價格:" + price);
    }
}

//車票工廠,以出發地和目的地爲key緩存車票
public class TicketFactory {
    static Map<String, Ticket> sTicketMap = new ConcurrentHashMap<String, Ticket>();

    public static Ticket getTicket(String from, String to) {
        String key = from + "-" + to;
        if(sTicketMap.containsKey(key)) {
            System.out.println("使用緩存==>"+key);
            return sTicketMap.get(key);
        }else{
            System.out.println("創建對象==>"+key);
            Ticket ticket = new TrainTicket(from, to);
            sTicketMap.put(key,ticket);
            return ticket;
        }
    }
}

// 測試
public class Test {
    public static void main(String[] args){
        Ticket ticket01 = TicketFactory.getTicket("北京", "商丘");
        ticket01.showTicketInfo("硬座");
        Ticket ticket02 = TicketFactory.getTicket("北京", "商丘");
        ticket02.showTicketInfo("硬臥");
        Ticket ticket03 = TicketFactory.getTicket("北京", "商丘");
        ticket03.showTicketInfo("軟臥");
    }
}

輸出結果:

創建對象==>北京-商丘
購買 從 北京 到 商丘的 硬座火車票,價格:240
使用緩存==>北京-商丘
購買 從 北京 到 商丘的 硬臥火車票,價格:174
使用緩存==>北京-商丘
購買 從 北京 到 商丘的 軟臥火車票,價格:280

總結
享元模式實現比較簡單,但是作用卻是極其重要的。它可以大大減少應用程序創建的對象,降低程序內部的佔用,增強程序的性能,但它同時也提高了系統的複雜性,需要分離出外部狀態和內部狀態,而且外部狀態具有固化特性,不應該隨內部狀態改變而改變,否則導致系統的邏輯混亂。

享元模式的優缺點

享元模式大幅度降低內存中對象的數量,它做到這一點所付出的代價也是很高的:

  • 享元模式使得系統更加複雜。爲了使對象可以共享,需要將一些狀態外部化,這使得程序的邏輯複雜化
  • 享元模式將享元對象的狀態外部化,而讀取外部狀態使得運行時間稍微變長。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章