0. 前言
寫在最前面,本人的設計模式類博文,建議先看博文前半部分的理論介紹。再看后半部分的實例分析。最后再返回來復習一遍理論介紹,這時候你就會發現我在重點處標紅的用心,對于幫助你理解設計模式有奇效哦~本文原創。轉載請注明出處為SEU_Calvin的博客。
春運買火車票是一件瘋狂的事情。同一時刻會有大量的查票請求涌向server。server必須做出應答來滿足我們的購票需求。試想。這些請求包括著大量的反復,比方從A地到B地的車票情況。假設每次都反復創建一個車票查詢結果的對象,那么GC任務將很繁重。影響性能,這就用到了我們的享元模式。
當然也會有不反復的請求。比方我想購買從A地到B地的高鐵票。而你想買從A地到B地的動車票。
1. 享元模式模式介紹
享元模式定義:
享元模式以共享的方式高效地支持大量的細粒度對象。享元模式中僅僅有內部狀態(不會隨環境發生改變)能夠共享,在春運的樣例中代表詳細的從A地到B地,外部狀態(隨環境改變)不可共享,在樣例中代表客戶想購買從A地到B地的高鐵票還是動車票。
?
享元模式的使用場景:
假設一個應用程序須要創建大量的類似對象。須要用對象緩沖池時。
?
享元模式包括的角色:
(1)抽象享元Flyweight類:享元對象抽象基類或接口。
(2)詳細享元ConcreteFlyweight類:實現抽象享元類。
(3)享元工廠FlyweightFactory類:享元模式的核心模塊。負責管理享元對象池、創建享元對象,保證享元對象能夠被系統適當地共享。
當一個client對象調用一個享元對象的時候。享元工廠角色會檢查系統中是否已經有一個符合要求的享元對象,假設已有,享元工廠角色就提供這個已有的享元對象;假設沒有就創建一個。
2. 享元模式模式實例介紹
通過上面給出的角色類,我們能夠把文章開始時的樣例實現一下,代碼也比較簡單:
/*
*@SEU_Calvin
*@2016/12/31
*/
//抽象享元類
public interface Ticket{//顯示票價。參數為列車類型
public void showPrice(String type);
}//詳細享元類
public class ConcreteTicket implements Ticket {
String from;
String to;
public ConcreteTicket(String from,String to){this.from = from;this.to = to;
}@Override
public void showPrice(String type){
if(type.equals("Gaotie")){System.out.println("從"+from+"到"+to+"的高鐵票價為200元");
}else{System.out.println("從"+from+"到"+to+"的動車票價為120元");
}
}
} //享元工廠類
public class TicketFactory{
static Map<String,Ticket> map= new ConcurrentHashMap< String,Ticket >();
public static Ticket getTicket(String from,String to){String key = from+to;if(map.containsKey(key)){System.out.println("使用緩存查詢"+key);return map.get(key);
}else{System.out.println("創建對象查詢"+key);Ticket ticket = new ConcreteTicket(from,to);map.put(key, ticket);return ticket;
}
}
}//使用時
TicketFactory. getTicket("南京","杭州").showPrice("Gaotie");
TicketFactory. getTicket("南京","杭州").showPrice("Dongche");
從上面代碼能夠看出,我們利用了Map避免了大量查詢南京到杭州列車信息相關的ConcreteTicket實例對象的創建。避免了頻繁GC的發生。
從輸出結果也能夠看出第二次查詢即從緩存中獲取到ConcreteTicket對象。
在本例中內部狀態就是從南京到杭州,外部狀態是列車類型和價格,價格會隨著列車類型變化。
在JDK中的String類的相關屬性也符合了享元模式的實現原則,這就涉及到了常量池的概念,詳細的已經在從JVM角度比較equals和==的差別一文中介紹過了。感興趣的同學能夠參考。
3. 享元模式的優缺點比較
享元模式的長處:
享元模式大幅度地減少內存中對象的數量,提高了程序的性能。
?享元模式的缺點:
(1)為了使對象能夠共享。須要將一些狀態外部化,這使得程序的邏輯復雜化。
(2)享元模式須要額外維護對象緩存池。