Java設計模式之享元模式

版權聲明:本文出自汪磊的博客,轉載請務必註明出處。java

設計模式系列與數據結構算法系列爲本人知識的梳理,大致上沒有什麼新玩意,都是前人們工做經驗的結晶,好了,不囉嗦了,基礎的重要性懂得天然懂。等這兩個系列總結完在寫框架方面的,好的框架必然包含一種或多種設計模式與數據結構。算法

1、享元模式設計模式

享元模式解決的就是在有大量對象時,有可能會形成內存溢出,若是有相同的業務請求,直接返回在內存中已有的對象,避免從新建立,說白了就是對象的複用,而不是每次都直接新建立一個對象。緩存

享元模式核心就是相同或者類似對象的共享複用,分享的是對象相同的部分,而不一樣的部分用接口暴露出去根據環境動態的設置,而這在享元模式中分別叫作內部狀態與外部狀態。數據結構

接口暴露的就是對象能夠改變的部分,稱做外部狀態,而那些經過外部設置可是不容許共享的部分稱做內部狀態。而且外部狀態的改變不能影響內部狀態。框架

享元模式很重要一點是分離對象變與不變的部分,變化的部分經過接口提取,共享對象時須要外部本身設置,不變的部分能夠共享出去。ide

平常開發中,可以共享的內部狀態是有限的,所以經過享元模式共享的對象通常都設計爲較小的對象,它所包含的內部狀態較少,這種對象也稱爲細粒度對象。所謂內部狀態較少說白了就是對象的屬性大部分外部使用時均可以根據本身須要來設置。性能

咱們使用享元模式的目的就是使用共享技術來實現大量細粒度對象的複用。測試

好了,經過上面描述估計一部分同窗蒙圈了,這都是什麼玩意,接下來咱們經過實際代碼來看一下。this

假設這樣一個業務場景,咱們須要不一樣的玩具對象使用,而玩具的大小屬性一開始就設定好了,顏色屬性外部能夠本身根據須要設置。

根據上述需求,咱們就能夠提取出玩具對象的內部狀態爲大小屬性,不可外部隨意設置,而顏色屬性爲外部狀態,可根據須要自行設置。

抽象出享元對象接口:

public interface IToys {
void setColor(String color);

int getSize();
String getColor();
}

具體享元對象:

 1 public class SpecificToys implements IToys {  2     
 3     private String color;  4     private int size;  5 
 6     public SpecificToys(int size) {  7         this.size = size;  8  }  9 
10  @Override 11     public void setColor(String color) { 12         this.color = color; 13  } 14 
15     public String getColor() { 16         return color; 17  } 18 
19     public int getSize() { 20         return size; 21  } 22 
23     public void setSize(int size) { 24         this.size = size; 25  }26 }

具體共享對象是不容許直接外部使用建立的,這裏咱們須要定義一個工廠類,須要使用此對象所有由工廠類控制。

 1 public class ToysFactory {  2 
 3     //存儲共享對象
 4     private Map<Integer, IToys> cacheMap = new HashMap<>();  5 
 6     private static ToysFactory instance = null;  7     private ToysFactory(){}  8 
 9     public static ToysFactory getInstance(){ 10         if (null == instance){ 11             synchronized (ToysFactory.class){ 12                 if (null == instance){ 13                     instance = new ToysFactory(); 14  } 15  } 16  } 17         return instance; 18  } 19 
20     public IToys getIToysInstance(int size){ 21 
22         IToys iToys = cacheMap.get(size); 23         if (null == iToys){ 24             iToys = new SpecificToys(size); 25  cacheMap.put(size, iToys); 26  } 27         return iToys; 28  } 29 
30 }

工廠類核心就是cacheMap,存儲已經產生過的對象,獲取的時候先檢查內存中是否有對應對象緩存,有則直接複用。

最後測試一下:

 1 IToys iToys1 = ToysFactory.getInstance().getIToysInstance(1);  2 iToys1.setColor("red");  3 System.out.println(iToys1+"---"+iToys1.getSize()+"---"+iToys1.getColor());  4 
 5 IToys iToys2 = ToysFactory.getInstance().getIToysInstance(1);  6 iToys1.setColor("blue");  7 System.out.println(iToys2+"---"+iToys2.getSize()+"---"+iToys2.getColor());  8 
 9 IToys iToys3 = ToysFactory.getInstance().getIToysInstance(1); 10 iToys1.setColor("yellow"); 11 System.out.println(iToys3+"---"+iToys3.getSize()+"---"+iToys3.getColor());

打印以下:

1 com.wanglei55.mjavalib.SpecificToys@75b84c92---1---red 2 com.wanglei55.mjavalib.SpecificToys@75b84c92---1---blue 3 com.wanglei55.mjavalib.SpecificToys@75b84c92---1---yellow

看到了吧,這樣就實現了對象的複用,這裏的ToysFactory只能產生一種實例對象,要是想生產多種呢?本身思考一下。。。

2、享元模式總結

享元模式是提高系統性能的一種設計模式,經過享元模式咱們能夠實現對象的複用,從而減小建立對象的開銷,提高性能。

使用場景:

當咱們遇到須要建立大量相同或類似對象,而且這些對象的大部分屬性均可之外部化那麼此時就能夠考慮使用享元模式

此外享元模式的使用增長了系統的複雜度,咱們須要把對象的外部狀態與內部狀態區分開來,這些都是其缺點。

享元模式以共享的方式高效地支持大量的細粒度對象,享元對象能作到共享的關鍵是區份內部狀態和外部狀態。其中內部狀態是存儲在享元對象內部而且不會隨環境改變而改變的狀態,所以內部狀態能夠共享;外部狀態是隨環境改變而改變的、不能夠共享的狀態。

好了,享元模式介紹到此爲止了,但願對你有用。

相關文章
相關標籤/搜索