對象共享,避免創建多對象
享元模式的介紹
享元模式是對象池的一種實現,它的英文名字Flyweight,代表輕量級的意思,享元模式用來儘可能減少內存的使用量,它適合用於可能存在大量重複對象的場景,來緩存可共享的對象,達到對象的共享,避免創建過多的對象效果,這樣一來就可以提升性能、避免內存溢出等。
享元對象中的部分狀態是可以共享,可以共享的狀態稱爲內部狀態,內部狀態不會隨着環境變化;不可共享的狀態則稱之爲外部狀態,它們會隨着環境的改變而改變。在享元模式中會建立一個對象容器,在經典的享元模式中該容器爲一個Map,它的鍵是享元對象內部狀態,他的值就是享元對象本身。客戶端程序通過這個內部類狀態從享元工廠中獲取享元對象,如果有緩存則使用緩存對象,否則創建一個享元對象並存入容器中,這樣一來就避免了創建過多的對象問題。
享元模式定義
使用共享對象可有效地支持大量的細粒度的對象。
享元模式的使用場景
(1) 系統中存在大量的相似對象
(2) 細粒度的對象都具備較接近的外部狀態,而且內部狀態與環境無關,也就是說對象沒有特定身份。
(3) 需要緩衝池的場景
享元模式的示例
每年到了過年是最頭疼的時候,買火車票或者大巴票是一件很困難的事,無數人用刷票軟件在想服務端發出請求,對每一個請求必須做出應答。在用戶設置好出發地和目的地之後,沒發送一次請求都返回一個查詢的車票結果。爲了偏於理解,我們假設每次返回的只有一趟列車的車票。那麼當數以萬計的人不間斷在請求數據時如果每次都重新創建一個查詢的結果,那麼必然會造成大量重複對象的創建、銷燬,是得GC任務繁重、內存佔用率居高不下。而這類問題通常通過享元模式就能夠得到很好的改善,從A城市到B城市的車輛是有限的,車上的鋪位也就是軟臥、硬臥、硬座和站票4種。我們可以將這些共有的對象緩存起來,在用戶查詢時優先使用緩存,如果沒有緩存則重新創建。這樣成千上萬的對象變爲可選擇的有限數量。
/*
* Ticket接口
* 該接口定義展示車票信息函數
* */
publicinterfaceTicket {
publicvoid showTicketInfo(Stringbunk);
}
/*
* 該類是Ticket接口的一個具體實現類
* */
classTrainTicket implements Ticket{
publicString from;//出發地
publicString to;//目的地
publicString bunk;//鋪位
publicintprice;//價格
public TrainTicket(Stringfrom,String to){
this.from=from;
this.to=to;
}
publicvoidshowTicketInfo(String bunk) {
// TODOAuto-generated method stub
price=newRandom().nextInt(300);
System.out.println("購買從"+from+"到"+to+"的"+bunk+"火車票"+",價格:"+price);
}
/*
* 該類是是車票工廠,以出發地和目的地爲key緩存車票
* */
publicclassTicketFactory {
staticMap<String,Ticket> map=newConcurrentHashMap();
/**
* @paramargs
*/
publicstaticTicket getTicket(String from,String to) {
String key=from+to;
if(map.containsKey(key)){
System.out.println("使用緩存");
returnmap.get(key);
}else{
System.out.println("創建對象");
Ticket ticket=newTrainTicket(from, to);
map.put(key,ticket);
returnticket;
}
}
}
/*
* 該類與預測是結果
* */
publicclass main{
/**
* @paramargs
*/
publicstaticvoid main(String[]args) {
// TODOAuto-generated method stub
TicketFactory.getTicket("鄭州", "杭州").showTicketInfo("軟臥");
TicketFactory.getTicket("杭州", "鄭州").showTicketInfo("硬座");
TicketFactory.getTicket("鄭州", "杭州").showTicketInfo("硬臥");
TicketFactory.getTicket("鄭州", "杭州").showTicketInfo("硬座");
TicketFactory.getTicket("鄭州", "杭州").showTicketInfo("軟臥");
TicketFactory.getTicket("杭州", "鄭州").showTicketInfo("硬座");;
TicketFactory.getTicket("鄭州", "杭州").showTicketInfo("硬臥");;
TicketFactory.getTicket("鄭州", "杭州").showTicketInfo("硬座");;
}
}