經過上篇的講述,咱們知道裝飾模式,特別適合對某個類型的對象,動態的增長新的職責,應用程序就像使用原來的對象同樣使用對象新增的裝飾html
後的功能,裝 飾模式就好像是穿了一層層的外殼,這樣的方式避免了經過繼承來爲類型添加新的職責的形式可取,經過繼承的方式容易形成子類的膨java
脹,可是當裝飾類太多的時 候,也是個難以維護的問題,至少是在裝飾對象的時候,咱們可能須要多步操做來完成對象的裝飾,這時候咱們能夠同上面設計模式
提出的改進的方案,來完成自動配置裝飾 模式,記錄操做模式的狀態,能夠進行有效的回滾操做,以完成撤銷操做。緩存
咱們先來回顧下裝飾模式的使用場景:架構
一、當咱們須要爲某個現有的對象,動態的增長一個新的功能或職責時,能夠考慮使用裝飾模式。分佈式
二、適應於某個對象的職責常常發生變化或者常常須要動態的增長職責,避免由於這種爲了適應這樣的變化,而增長繼承子類擴展的方式,由於ide
這種方式爲 形成,子類膨脹的速度過快,難以控制。函數
本篇咱們將會講述結構性模式中的另一個很是有用的模式-享元模式,享元模式的特色是,複用咱們內存中已存在的對象,下降系統建立對象實例性能
的性能消耗。在.NET下的值類型和引用類型的內存分配機制,我這裏就不作詳細的講解了,包括引用類型與值類型之間的裝箱和拆箱的操做,這個具體字體
的能夠參考園子裏面的關於這方面的文章的討論。
咱們來給出個簡單的享元模式的應用先後的對比圖,大概咱們就知道享元模式的重要做用了。
咱們這裏以繪製一個有樣式的字體來講明吧,有的時候咱們想繪製一個純色的文字,好比紅色,那麼咱們可能須要建立不少的實例,一般來講,這些
實例的差異不大,這個時候,咱們能夠考慮複用其中建立的某個實例,而不用去new這麼多相同的對象,來完成這樣的工做。咱們下面以這個例子來講
明,使用享元模式的先後對比的狀況。
使用享元模式前:
使用享元模式後:
經過上圖咱們能夠大概的看出享元模式的目的是什麼,本篇將會從如下幾點出發,講述享元模式的應用。
一、享元模式的特色和場景。
二、享元模式的經典實現。
三、享元模式的其餘方案。
四、享元模式小結。
下面咱們來看下享元模式的類圖吧:
a、上篇回顧。
b、摘要。
c、本文大綱。
d、享元模式的特色及使用場景。
e、享元模式的經典實現。
f、享元模式的其餘方案。
g、享元模式使用總結。
h、系列進度。
i、下篇預告。
享元模式的意圖是經過共享有效支持大量細粒度的對象,來提供應用程序的性能,節省系統中重複建立對象實例的性能消耗,這個怎麼理解呢?其實就是如下幾點的含義:
一、當咱們系統中某個對象類型的實例較多的狀況。
二、而且要求這些實例進行分類後,發現真正有區別的分類不多的狀況。
例如咱們的生活中不少的場景,咱們在使用拼音輸入的法的時候,若是說咱們每一個字都是new一個對象實例的操做的話,那麼內存中的實例就太可
怕,這個時候,咱們是否是能夠考慮將這些重複的字體在內存中只是建立一次,而是經過複用對象的形式,來組織一些可能有多個字符重複的內容呢?
也許這是一個不錯的主意,咱們來看看這個示例的過程吧。
一、當咱們發現某個類型的對象有大量的實例時,咱們是否能夠對這些實例進行分類,通過分類後,咱們發現只有不多的類別的狀況下。
二、咱們發現經過使用享元模式後可以提升系統的性能和不會帶來更多的複雜度時。
享元模式通常是給出本地內存資源節省的一個方案,並不適合互聯網上的分佈式應用的狀況,不過享元模式對於排他性的要求資源的控制,是個不
錯的選擇的。
咱們下面來根據上面的咱們對輸入法中的字體來進行分析,給出相關的示例代碼:
字體類型的基類:
public class FontBase
{
private List<string> font = new List<string>();private string fontName;
public FontBase(string name)
{
this.fontName = name;
}public FontBase AddFont(string font)
{
this.font.Add(font);
return this;
}
public virtual string FontName
{
get
{
return this.fontName;
}
}
}具體的文字類型類:
public class ChineseFont : FontBase
{
public ChineseFont()
: base("ChineseFont")
{
base.AddFont("ChineseFont");
}
}public class EnglishFont : FontBase
{
public EnglishFont()
: base("EnglishFont")
{
base.AddFont("EnglishFont");
}
}具體的建立工廠類:
public class FontFactory
{
private Dictionary<string, FontBase> fonts = new Dictionary<string, FontBase>();public FontBase Create(string name)
{
FontBase fontBase = fonts[name];
if (fontBase != null)
return fontBase;fontBase = (FontBase)Activator.CreateInstance(Type.GetType(name));
return fontBase;
}
}經過上面實例的講解咱們知道,咱們經過緩存對象類型的形式來控制對象實例的建立過程,經典的模式中沒有體現共享的狀態,好比說咱們在外部可能對於
享元對象來講是不共享的,內部是共享的。下面咱們來看看享元模式的變種吧。
對於上面的經典方案帶來的問題,可能咱們須要更好的考慮,咱們如何應對多種對象類型,咱們如何管理並共享這些對象實例,這些都是咱們須要考慮的問
題,通過上面的思考,咱們這裏能夠參考咱們平時開發的ORM中的鏈接池的思路,咱們這裏對享元模式提供-對象池的技術。
咱們在配置文件中控制對象池中的某個類型對象實例的數量,對象的生命週期的時間,默認初始化多少個對象實例,以提早準備,爲後續的使用提供服務。
咱們這裏能夠設計出這個專門的對象池,咱們能夠提供以下的功能:
一、根據對象類型動態的建立對象實例。
二、根據對象池中的配置,在對象池中找到空閒的實體提供給程序調用,減小建立對象的次數。
三、咱們須要設計每一個類型的緩衝池,經過把對象進行緩存,×××能。若是對象池中的對象長期不會調用,那麼咱們會提供一個銷燬對象的機制。
咱們來看看對象池的設計結構吧:
經過上面的幾個組件,來協調完成對象池的工做。
這裏給出相關的示例代碼:
咱們先給出配置文件配置緩衝池的配置信息:
<?xml version="1.0" encoding="utf-8" ?> <Cache> <ObjectSection name="" type=""/> <ObjectCache> <object name="" type="" max="" timeout="" /> <object name="" type="" max="" timeout="" /> <object name="" type="" max="" timeout="" /> <object name="" type="" max="" timeout="" /> <object name="" type="" max="" timeout="" /> <object name="" type="" max="" timeout="" /> <object name="" type="" max="" timeout="" /> <object name="" type="" max="" timeout="" /> <object name="" type="" max="" timeout="" /> </ObjectCache> </Cache> 咱們來看看具體的工廠類:public class ObjectFactory { public static T Build<T>() where T:class,new() { return new T(); } }咱們來看看具體的緩存類:public class ObjectCache { private static Dictionary<Type, object> cache =null; public static ObjectCache() { cache = new Dictionary<Type, object>(); } public void Cache<T>(T item) { cache.Add(typeof(T),item); } public void GetObjectFromCache<T>( out T item) { if (cache[typeof(T)] != null) item = cache[typeof(T)]; } }
享元模式的主旨意在經過共享對象節省整體資源,不過共享對象將致使資源訪問上的一些問題,包括對象實例的銷燬,還包括線程間的共享和線程
內的共享是不一樣的,咱們知道,通常線程退出的時候,會自動釋放線程內部的申請的資源,.NET會自動經過GC來回收,可是對於線程間共享的對象也
許不會自動回收,這些內容須要宿主進程來進行回收,固然可能這些咱們也能夠經過對象池來完成這樣的回收機制。 或者說也能夠參考操做系統中的
隊列的狀況,經過回調函數來通知進行對象的回收等。咱們在對於項目中須要大量實例對象的建立工做的時候,咱們就考慮一下是否是須要享元模式的
應用了,但願你們能在項目中找到合適的切入點,使用合適的模式來提升程序的適應性和健壯性。因爲本人水平有限,不足或者錯誤之處,還請你們批
評指出。
建立型
結構型
七、系統架構技能之設計模式-代理模式
行爲型
一、系統架構技能之設計模式-命令模式
二、系統架構技能之設計模式-觀察者模式
三、系統架構技能之設計模式-策略模式
四、系統架構技能之設計模式-職責模式
五、系統架構技能之設計模式-模板模式
六、系統架構技能之設計模式-中介者模式
七、系統架構技能之設計模式-解釋器模式
下篇咱們將開始介紹結構性模式中的-代理模式。代理模式就是爲了將某些對象的複雜性隱藏起來,使咱們使用複雜對象的代理,就像使用簡單對象同樣,下篇我
們將會從幾個方面講解代理模式的應用,但願你們多多提出不一樣的已經和建議。