Java設計模式之享元模式
版權宣告:本文出自汪磊的部落格,轉載請務必註明出處。
設計模式系列與資料結構算法系列為本人知識的梳理,大體上沒有什麼新玩意,都是前人們工作經驗的結晶,好了,不囉嗦了,基礎的重要性懂得自然懂。等這兩個系列總結完在寫框架方面的,好的框架必然包含一種或多種設計模式與資料結構。
一、享元模式
享元模式解決的就是在有大量物件時,有可能會造成記憶體溢位,如果有相同的業務請求,直接返回在記憶體中已有的物件,避免重新建立,說白了就是物件的複用,而不是每次都直接新建立一個物件。
享元模式核心就是相同或者相似物件的共享複用 ,分享的是物件相同的部分,而不同的部分用介面暴露出去根據環境動態的設定,而這在享元模式中分別叫做內部狀態與外部狀態。
介面暴露的就是物件可以改變的部分,稱作外部狀態, 而那些通過外部設定但是不允許共享的部分稱作內部狀態。並且外部狀態的改變不能影響內部狀態。
享元模式很重要一點是分離物件變與不變的部分,變化的部分通過介面提取,共享物件時需要外部自己設定,不變的部分可以共享出去。
日常開發中,能夠共享的內部狀態是有限的,因此通過享元模式共享的物件一般都設計為較小的物件,它所包含的內部狀態較少,這種物件也稱為 細粒度物件。 所謂內部狀態較少說白了就是物件的屬性大部分外部使用時都可以根據自己需要來設定。
我們使用享元模式的目的就是使用共享技術來實現大量細粒度物件的複用。
好了,通過上面描述估計一部分同學蒙圈了,這都是什麼玩意,接下來我們通過實際程式碼來看一下。
假設這樣一個業務場景,我們需要不同的玩具物件使用,而玩具的大小屬性一開始就設定好了,顏色屬性外部可以自己根據需要設定。
根據上述需求,我們就可以提取出玩具物件的內部狀態為大小屬性,不可外部隨意設定,而顏色屬性為外部狀態,可根據需要自行設定。
抽象出享元物件介面:
public interface IToys { void setColor(String color); int getSize(); String getColor(); }
具體享元物件:
1 public class SpecificToys implements IToys { 2 3private String color; 4private int size; 5 6public SpecificToys(int size) { 7this.size = size; 8} 9 10@Override 11public void setColor(String color) { 12this.color = color; 13} 14 15public String getColor() { 16return color; 17} 18 19public int getSize() { 20return size; 21} 22 23public void setSize(int size) { 24this.size = size; 25}26 }
具體共享物件是不允許直接外部使用建立的,這裡我們需要定義一個工廠類,需要使用此物件全部由工廠類控制。
1 public class ToysFactory { 2 3//儲存共享物件 4private Map<Integer, IToys> cacheMap = new HashMap<>(); 5 6private static ToysFactory instance = null; 7private ToysFactory(){} 8 9public static ToysFactory getInstance(){ 10if (null == instance){ 11synchronized (ToysFactory.class){ 12if (null == instance){ 13instance = new ToysFactory(); 14} 15} 16} 17return instance; 18} 19 20public IToys getIToysInstance(int size){ 21 22IToys iToys = cacheMap.get(size); 23if (null == iToys){ 24iToys = new SpecificToys(size); 25cacheMap.put(size, iToys); 26} 27return 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只能產生一種例項物件,要是想生產多種呢?自己思考一下。。。
二、享元模式總結
享元模式是提升系統性能的一種設計模式,通過享元模式我們可以實現物件的複用,從而減少建立物件的開銷,提升效能。
使用場景:
當我們遇到需要建立大量相同或相似物件,並且這些物件的大部分屬性都可以外部化那麼此時就可以考慮使用享元模式
此外享元模式的使用增加了系統的複雜度,我們需要把物件的外部狀態與內部狀態區分開來,這些都是其缺點。
享元模式以共享的方式高效地支援大量的細粒度物件,享元物件能做到共享的關鍵是區分內部狀態和外部狀態。其中內部狀態是儲存在享元物件內部並且不會隨環境改變而改變的狀態,因此內部狀態可以共享;外部狀態是隨環境改變而改變的、不可以共享的狀態。
好了,享元模式介紹到此為止了,希望對你有用。