c#設計模式系類:亨元模式
一、引言
在軟件開發過程中,如果我們需要重復使用某個對象的時候,如果我們重復地使用new創建這個對象的話,這樣我們在內存就需要多次去申請內存空間了,這樣可能出現內存使用越來越多的情況,這樣的問題是非常嚴重,然而亨元模式可以解決這個問題,下面我們一起具體看看亨元模式是如何解決這個問題的。
二、享元模式的詳細介紹
既然亨元模式可以解決重復使用new創建對象的問題,下面讓我們分析下如何去解決上面那個問題,既然都是同一個對象,能不能只創建一個對象,然後下次需要創建這個對象的時候,讓它直接用已經創建好了的對象就好了呢,也就是說讓一個對象共享。這個也是亨元模式的實現精髓所在。
2.1 定義
介紹完享元模式的精髓之後,讓我們具體看看享元模式的正式定義:
亨元模式——利用共享技術有效地支持大量細粒度的類實例來表示數據,亨元模式可以避免大量相識類的開銷,在軟件開發過程中如果需要大量細粒度的類實例來表示數據,而這些實例除了幾個參數外基本相同,這時候就可以使用亨元模式來大幅度減少需要類的實例數量。如果能把這些參數(指的這些類實例的不同參數)移動到類實例外面,在方法調用時將他們傳入盡量,這樣就可以通過共享大幅度減少單個實例的數目,然而我們把類實例外面的參數稱為亨元對象的外部狀態,把亨元對象內部參數稱為內部狀態,
- 內部狀態:在亨元對象的內部,並且不會隨著環境的改變而改變的共享部分
- 外部對象:隨環境的變化而改變的,部可以共享的部分。
2.2 亨元模式結構圖
2.3 亨元模式的組成
- 抽象亨元角色(Flyweight):此角色是所有的具體亨元類的基類,為這些類規定出需要實現的公共接口,那些需要外部狀態的操作可以通過調用方法已參數形式傳遞。
- 具體亨元角色(ConcreteFlyweight):實現抽象亨元角色所規定的接口,如果又內部狀態的化,可以在類內部定義。
- 亨元工廠角色(FlyweightFactory):本角色負責創建和管理亨元角色,本角色保證亨元對象可以被共享,當一個客戶端調用一個亨元對象的時候,亨元工廠角色檢查系統是否已經有一個符合的亨元對象,如果已經存在,就返回亨元對象,如果不存在就重新創建一個亨元對象
- 客戶端角色(Client):本角色需要存儲亨元對象的外部狀態
2.4亨元模式代碼實現
Flyweight類,它是所有具體亨元類的超類或接口,通過這個接口,Flyweight可以接受並作用於外部狀態
public abstract class Flywieght { public abstract void Operation(int extrinsicstate); }View Code
ConcreteFlyweight是繼承Flyweight超類或實現Flyweight接口,並為內部狀態增加存儲空間。
public class ConcreteFlyweight:Flywieght { public override void Operation(int extrinsicstate) { Console.WriteLine("具體的"+extrinsicstate); } }View Code
UnsharedConcreteFlyweight是 指那些不需要共享的Flyweight子類,因為Flyweight接口讓共享成為可能,但它並不強制共享
public class UnsharedConcreteFlyweight:Flywieght { public override void Operation(int extrinsicstate) { Console.WriteLine("不共享的具體Flywieght"+extrinsicstate); } }View CodeFlyweightFactory,是一個亨元工廠,用來創建並管理Flyweight對象,它主要是用來確保合理的共享Flyweight,當用戶請求一個Flyweight時,FlyweightFactory對象提供一個已創建的實例或者創建一個(如果不存在)
public class FlyweightFactory { private Hashtable flyweights = new Hashtable(); public FlyweightFactory() { flyweights.Add("X",new ConcreteFlyweight()); flyweights.Add("Y", new ConcreteFlyweight()); flyweights.Add("Z", new ConcreteFlyweight()); } public Flywieght GetFlyweight(string key) { return ((Flywieght)flyweights[key]) ; } }View Code
客戶端代碼
class Program { static void Main(string[] args) { int extrinsincstate = 10; FlyweightFactory f = new FlyweightFactory(); Flywieght fx = f.GetFlyweight("X"); fx.Operation(--extrinsincstate); Flywieght fy = f.GetFlyweight("Y"); fy.Operation(--extrinsincstate); Flywieght fz = f.GetFlyweight("Z"); fz.Operation(--extrinsincstate); UnsharedConcreteFlyweight uf = new UnsharedConcreteFlyweight(); uf.Operation(--extrinsincstate); Console.Read(); } }View Code
結果表示
具體的9 具體的8 具體的7 不共享的具體Flywieght6View Code
三、享元模式的實現要點:
面向對象很好地解決了抽象性的問題,但是作為一個運行在機器中的程序實體,我們需要考慮對象的代價問題。Flyweight設計模式主要解決面向對象的代價問題,一般不觸及面向對象的抽象性問題。
Flyweight采用對象共享的做法來降低系統中對象的個數,從而降低細粒度對象給系統帶來的內存壓力。在具體實現方面,要註意對象狀態的處理。
對象的數量太大從而導致對象內存開銷加大——什麽樣的數量才算大?這需要我們仔細的根據具體應用情況進行評估,而不能憑空臆斷。
- 享元模式的優點
- 享元模式的優點在於它能夠極大的減少系統中對象的個數。
- 元模式由於使用了外部狀態,外部狀態相對獨立,不會影響到內部狀態,所以享元模式使得享元對象能夠在不同的環境被共享。
- 享元模式的缺點
- 於享元模式需要區分外部狀態和內部狀態,使得應用程序在某種程度上來說更加復雜化了。
- 為了使對象可以共享,享元模式需要將享元對象的狀態外部化,而讀取外部狀態使得運行時間變
- 在下面所有條件都滿足時,可以考慮使用享元模式:
- 一個系統中有大量的對象;
- 這些對象耗費大量的內存;
- 這些對象中的狀態大部分都可以被外部化
- 這些對象可以按照內部狀態分成很多的組,當把外部對象從對象中剔除時,每一個組都可以僅用一個對象代替軟件系統不依賴這些對象的身份,
滿足上面的條件的系統可以使用享元模式。但是使用享元模式需要額外維護一個記錄子系統已有的所有享元的表,而這也需要耗費資源,所以,應當在有足夠多的享元實例可共享時才值得使用享元模式。
通過叠代來使用模式,別為了模式而模式
c#設計模式系類:亨元模式