Android設計模式(二十一)-享元模式

原文地址 http://blog.csdn.net/qq_25806863/article/details/69952037

享元模式是對象池的一種實現。類似於線程池,線程池可以避免不停的創建和銷燬多個對象,消耗性能。享元模式也是爲了減少內存的使用,避免出現大量重複的創建銷燬對象的場景。

享元模式用在一批相同或相似的對象上,這些對象有可以共享的內部狀態和各自不同的外部狀態。

享元模式中會有一個工廠,工廠維護着一個容器,容器以鍵值對的方式存儲,鍵是對象的內部狀態,也就是共享的部分,值就是對象本身。

客戶端從這個工廠獲取對象,如果容器中存在這個對象就直接返回,不存在再創建新的對象並存入容器,避免了大量重複創建對象。

定義

使用共享對象有效的支持大量的細粒度對象的複用。

使用場景

  • 系統存在大量相似或相同的對象。
  • 這些對象有較接近的外部狀態。
  • 需要緩衝池時。

UML

這裏寫圖片描述

  • Flyweight:享元對象抽象類或接口。
  • ConcreteFlyweight:具體的享元對象
  • FlyweightFactory:享元工廠,管理對象池和創建享元對象。

簡單實現

以查詢火車票價爲例。假如每張車票信息都是一個對象,當有很多人在查詢一個車票信息時,系統就會重複創建這個車票信息返回給每個人,這樣會不停的創建和銷燬對象,引發頻繁的GC,影響效率。

車票是有限的,結構是一樣的,內容是相似的,這裏簡化一下,假設車票上只有始發地,到達地,座位類型,票價四個內容。所以,如果緩存下來車票的話,就不管有多少人查詢,都不會頻繁的創建銷燬對象了。

把始發地和到達地看做是內部可以共享的狀態,當做緩存的鍵,整個車票對象爲值。

抽象的車票,提供一個方法展示車票信息,傳入信息是要查詢的座位類型:

public interface Ticket {
    void showInfo(String type);
}

具體的車票,這裏每次查詢的事隨機生成票價:

public class ConcreteTicket implements Ticket {
    private String from;
    private String to;
    private int price;
    private String type;

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

    }

    @Override
    public void showInfo(String type) {
        price = new Random().nextInt(500);
        this.type=type;
        System.out.println("從"+from+"到"+to+"的"+this.type+"票價是"+price);
    }
}

車票工廠:

public class TicketFactory {
    private static Map<String,Ticket> tickets = new HashMap<>();

    public static Ticket getTicket(String from,String to){
        String key = from+to;
        if (tickets.containsKey(key)){
            System.out.println("從緩存中獲取");
            return tickets.get(key);
        }else {
            System.out.println("新建對象");
            Ticket ticket = new ConcreteTicket(from,to);
            tickets.put(key,ticket);
            return ticket;
        }
    }
}

客戶端調用:

public class Client {
    public static void main(String[] args) {
        TicketFactory.getTicket("A","B").showInfo("硬座");
        TicketFactory.getTicket("A","B").showInfo("硬臥");
        TicketFactory.getTicket("C","B").showInfo("硬臥");
    }
}

輸出:
這裏寫圖片描述

總結

享元模式的核心就在享元工廠,因爲享元對象有可共享的內部狀態部分和不可共享的外部狀態部分,因此,內部可共享的就交給工廠去維護處理了,而外部可變的就可以交給客戶端去實現。

優點

  • 大大減少系統創建的對象,降低內存總對象的數量,降低程序佔用的內存,增強系統的性能。

缺點

  • 將對象分爲內部狀態和外部狀態兩部分,導致系統變複雜,邏輯也更復雜。
  • 將享元對象的狀態外部化,而讀取外部狀態使得運行時間稍微變長。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章