天天看點

設計模式系列-享元模式

      通過上篇的講述,我們知道裝飾模式,特别适合對某個類型的對象,動态的增加新的職責,應用程式就像使用原來的對象一樣使用對象新增的裝飾 後的功能,裝 飾模式就好像是穿了一層層的外殼,這樣的方式避免了通過繼承來為類型添加新的職責的形式可取,通過繼承的方式容易造成子類的膨 脹,但是當裝飾類太多的時 候,也是個難以維護的問題,至少是在裝飾對象的時候,我們可能需要多步操作來完成對象的裝飾,這時候我們可以同上面 提出的改進的方案,來完成自動配置裝飾 模式,記錄操作模式的狀态,可以進行有效的復原操作,以完成撤銷操作。       我們先來回顧下裝飾模式的使用場景:       1、當我們需要為某個現有的對象,動态的增加一個新的功能或職責時,可以考慮使用裝飾模式。       2、适應于某個對象的職責經常發生變化或者經常需要動态的增加職責,避免因為這種為了适應這樣的變化,而增加繼承子類擴充的方式,因為 這種方式為 造成,子類膨脹的速度過快,難以控制。
    本篇我們将會講述結構性模式中的另外一個非常有用的模式-享元模式,享元模式的特點是,複用我們記憶體中已存在的對象,降低系統建立對象執行個體 的性能消耗。在.NET下的值類型和引用類型的記憶體配置設定機制,我這裡就不做詳細的講解了,包括引用類型與值類型之間的裝箱和拆箱的操作,這個具體 的可以參考園子裡面的關于這方面的文章的讨論。     我們來給出個簡單的享元模式的應用前後的對比圖,大概我們就知道享元模式的重要作用了。     我們這裡以繪制一個有樣式的字型來說明吧,有的時候我們想繪制一個純色的文字,比如紅色,那麼我們可能需要建立很多的執行個體,通常來說,這些 執行個體的差别不大,這個時候,我們可以考慮複用其中建立的某個執行個體,而不用去new這麼多相同的對象,來完成這樣的工作。我們下面以這個例子來說 明,使用享元模式的前後對比的情況。     使用享元模式前:
設計模式系列-享元模式
    使用享元模式後:
設計模式系列-享元模式
    通過上圖我們可以大概的看出享元模式的目的是什麼,本篇将會從以下幾點出發,講述享元模式的應用。     1、享元模式的特點和場景。     2、享元模式的經典實作。     3、享元模式的其他方案。     4、享元模式小結。 下面我們來看下享元模式的類圖吧:
設計模式系列-享元模式
       a、上篇回顧。        b、摘要。        c、本文大綱。        d、享元模式的特點及使用場景。        e、享元模式的經典實作。        f、享元模式的其他方案。        g、享元模式使用總結。        h、系列進度。        i、下篇預告。
      享元模式的意圖是通過共享有效支援大量細粒度的對象,來提供應用程式的性能,節省系統中重複建立對象執行個體的性能消耗,這個怎麼了解呢?其實就是以下幾點的含義: 1、當我們系統中某個對象類型的執行個體較多的情況。 2、并且要求這些執行個體進行分類後,發現真正有差別的分類很少的情況。       例如我們的生活中很多的場景,我們在使用拼音輸入的法的時候,如果說我們每個字都是new一個對象執行個體的操作的話,那麼記憶體中的執行個體就太可 怕,這個時候,我們是不是可以考慮将這些重複的字型在記憶體中隻是建立一次,而是通過複用對象的形式,來組織一些可能有多個字元重複的内容呢? 也許這是一個不錯的主意,我們來看看這個示例的過程吧。
設計模式系列-享元模式
         1、當我們發現某個類型的對象有大量的執行個體時,我們是否可以對這些執行個體進行分類,經過分類後,我們發現隻有很少的類别的情況下。          2、我們發現通過使用享元模式後能夠提高系統的性能和不會帶來更多的複雜度時。       享元模式一般是給出本地記憶體資源節省的一個方案,并不适合網際網路上的分布式應用的情況,不過享元模式對于排他性的要求資源的控制,是個不 錯的選擇的。
      我們下面來根據上面的我們對輸入法中的字型來進行分析,給出相關的示例代碼:       字型類型的基類:     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中的連接配接池的思路,我們這裡對享元模式提供-對象池的技術。

            我們在配置檔案中控制對象池中的某個類型對象執行個體的數量,對象的生命周期的時間,預設初始化多少個對象執行個體,以提前準備,為後續的使用提供服務。

            我們這裡可以設計出這個專門的對象池,我們可以提供如下的功能:

            1、根據對象類型動态的建立對象執行個體。

            2、根據對象池中的配置,在對象池中找到空閑的實體提供給程式調用,減少建立對象的次數。

            3、我們需要設計每個類型的緩沖池,通過把對象進行緩存,提供性能。如果對象池中的對象長期不會調用,那麼我們會提供一個銷毀對象的機制。

我們來看看對象池的設計結構吧:
設計模式系列-享元模式
通過上面的幾個元件,來協調完成對象池的工作。 這裡給出相關的示例代碼: 我們先給出配置檔案配置緩沖池的配置資訊: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <code>&lt;?</code><code>xml</code> <code>version="1.0" encoding="utf-8" ?&gt;</code> <code>&lt;</code><code>Cache</code><code>&gt;</code> <code>  </code><code>&lt;</code><code>ObjectSection</code> <code>name="" type=""/&gt;</code> <code>  </code><code>&lt;</code><code>ObjectCache</code><code>&gt;</code> <code>    </code><code>&lt;</code><code>object</code> <code>name="" type="" max="" timeout="" /&gt;</code> <code>  </code><code>&lt;/</code><code>ObjectCache</code><code>&gt;</code> <code>&lt;/</code><code>Cache</code><code>&gt;</code> <code>我們來看看具體的工廠類:</code> <code>&lt;</code><code>div</code> <code>class="cnblogs_Highlighter"&gt;&lt;</code><code>pre</code> <code>class="brush:html"&gt;    public class ObjectFactory</code> <code>    </code><code>{</code> <code>        </code><code>public static T Build&lt;</code><code>T</code><code>&gt;() where T:class,new()</code> <code>        </code><code>{</code> <code>            </code><code>return new T();</code> <code>        </code><code>}</code> <code>    </code><code>}</code> <code>&lt;/</code><code>pre</code><code>&gt;</code> <code>&lt;/</code><code>div</code><code>&gt;</code> <code>我們來看看具體的緩存類:</code> 18 19 20 21 22 <code>&lt;</code><code>div</code> <code>class="cnblogs_Highlighter"&gt;&lt;</code><code>pre</code> <code>class="brush:html"&gt;    public class ObjectCache</code> <code>        </code><code>private static Dictionary&lt;</code><code>Type</code><code>, object&gt; cache =null;</code> <code>        </code><code>public static ObjectCache()</code> <code>            </code><code>cache = new Dictionary&lt;</code><code>Type</code><code>, object&gt;();</code> <code>        </code><code>public void Cache&lt;</code><code>T</code><code>&gt;(T item)</code> <code>            </code><code>cache.Add(typeof(T),item);</code> <code>        </code><code>public void GetObjectFromCache&lt;</code><code>T</code><code>&gt;( out T item)</code> <code>            </code><code>if (cache[typeof(T)] != null)</code> <code>                </code><code>item = cache[typeof(T)];</code>
      享元模式的主旨意在通過共享對象節省總體資源,不過共享對象将導緻資源通路上的一些問題,包括對象執行個體的銷毀,還包括線程間的共享和線程 内的共享是不同的,我們知道,一般線程退出的時候,會自動釋放線程内部的申請的資源,.NET會自動通過GC來回收,但是對于線程間共享的對象也 許不會自動回收,這些内容需要宿主程序來進行回收,當然可能這些我們也可以通過對象池來完成這樣的回收機制。  或者說也可以參考作業系統中的 隊列的情況,通過回調函數來通知進行對象的回收等。我們在對于項目中需要大量執行個體對象的建立工作的時候,我們就考慮一下是不是需要享元模式的 應用了,希望大家能在項目中找到合适的切入點,使用合适的模式來提高程式的适應性和健壯性。由于本人水準有限,不足或者錯誤之處,還請大家批 評指出。 八、系列進度 建立型         1、系統架構技能之設計模式-單件模式         2、系統架構技能之設計模式-工廠模式         3、系統架構技能之設計模式-抽象工廠模式         4、系統架構技能之設計模式-建立者模式         5、系統架構技能之設計模式-原型模式 結構型         1、系統架構技能之設計模式-組合模式         2、系統架構技能之設計模式-外觀模式         3、系統架構技能之設計模式-擴充卡模式         4、系統架構技能之設計模式-橋模式         5、系統架構技能之設計模式-裝飾模式         6、系統架構技能之設計模式-享元模式         7、系統架構技能之設計模式-代理模式 行為型         1、系統架構技能之設計模式-指令模式         2、系統架構技能之設計模式-觀察者模式         3、系統架構技能之設計模式-政策模式         4、系統架構技能之設計模式-職責模式         5、系統架構技能之設計模式-模闆模式         6、系統架構技能之設計模式-中介者模式         7、系統架構技能之設計模式-解釋器模式 九、下篇預告         下篇我們将開始介紹結構性模式中的-代理模式。代理模式就是為了将某些對象的複雜性隐藏起來,使我們使用複雜對象的代理,就像使用簡單對象一樣,下篇我 們将會從幾個方面講解代理模式的應用,希望大家多多提出不同的已經和建議。 本文轉自何戈洲部落格園部落格,原文連結:http://www.cnblogs.com/hegezhou_hot/archive/2010/12/12/1903728.html,如需轉載請自行聯系原作者