我們都知道,現實世界的東西都是通過用物件的形式來描述以此讓它們存在於我們的軟體世界裡,所以,在軟體世界中,現實世界的任何東西都能以物件的形式存在於軟體世界中,大到宇宙星辰,小到砂礫塵埃,毫不客氣的說,我們程式猿們如果想要個女朋友的話,直接建立一個女朋友類,然後new它一下就能輕鬆脫單了(咳咳),扯得太遠了,讓我們進入今天的正題,享元模式,所謂的享元,就是共享物件,那何為共享物件呢?我們在new一個物件的時候,電腦會在記憶體中開闢一個空間用來儲存我們這個物件,今天,我們的享元模式,就是共享這個空間,好了,前提說完,我們先建立一個享元物件吧
abstract class Flyweight { public abstract void Operation(int extrinsicetate); }
很簡單,Flyweight就是我們今天的享元物件的抽象,抽象類建立完成,按照國際慣例我們就要去實現它
class ConcreteFlyweight : Flyweight { public override void Operation(int extrinsicetate) { Console.WriteLine("具體Flyweight:" + extrinsicetate); } }
實現類也是超級簡單,重寫父類方法,然後在內部列印一句話,這裡的extrinsicetate引數我們可以理解為編號,用來區分;到這裡,享元類是建立完成了,如何做到享元呢,其實我們直接可以就new它,然後通過賦值的形式就可以實現享元了,但是我們的追求應該不止於此,我們要把享元類管理起來,我們可以設定在一個地方統一new物件和管理,這樣當我們需要物件的時候直接拿就好了,這就是我們今天享元模式最關鍵的一個工廠類了,享元工廠
class FlyweightFactory { private Hashtable flyweights = new Hashtable(); private static FlyweightFactory factory = new FlyweightFactory(); private FlyweightFactory() { flyweights.Add("X", new ConcreteFlyweight()); flyweights.Add("Y", new ConcreteFlyweight()); flyweights.Add("Z", new ConcreteFlyweight()); } public static FlyweightFactory getFactory() { return factory; } public Flyweight GetFlyweight(string key) { if (flyweights.ContainsKey(key)) return ((Flyweight)flyweights[key]); else { flyweights.Add(key, new ConcreteFlyweight()); return ((Flyweight)flyweights[key]); } } }
FlyweightFactory就是我們的享元工廠,首先,我們建立了兩個私有物件,一個是我們的享元工廠,另一個是我們用來儲存享元物件的,這裡我們用了單例模式來限制我們的享元工廠只能有一個,所有需要享元物件的都只能到我這裡來拿,然後我們再看GetFlyweight方法,這個方法就是判斷hashtable中有沒有我們需要的享元物件,如果有就返回,沒有就建立一個加入到hashtable中然後再返回,這裡我們可以看到if和else中有一段相同的程式碼,那我們是不是應該把它給提煉出來呢,而且if和else的大括號看起來也不清爽,我們給它修剪修剪
public Flyweight GetFlyweight(string key) { if (!flyweights.ContainsKey(key)) flyweights.Add(key, new ConcreteFlyweight()); return ((Flyweight)flyweights[key]); }
好了,由原先的六行程式碼變成現在的一行程式碼,看起來也清爽了不少啊,而且邏輯也比較清晰:當hashtable中不存在請求的鍵時,我們就建立這個鍵的物件,然後返回物件,OK,完美,三個物件,就完成我們今天所要講的享元模式了,接下來,讓我們看看上端呼叫實現吧
class Program { static void Main(string[] args) { int extrinsicstate = 0; FlyweightFactory f = FlyweightFactory.getFactory(); Flyweight fx = f.GetFlyweight("X"); fx.Operation(++extrinsicstate); Flyweight fy = f.GetFlyweight("Y"); fy.Operation(++extrinsicstate); Flyweight fz = f.GetFlyweight("Z"); fz.Operation(++extrinsicstate); Console.Read(); } }
首先,我們通過getFactory方法獲取享元工廠,然後再通過鍵來獲取具體的享元類,這裡注意的是我們建立了三個不同種類的享元類,分別是X、Y、Z,這三個類他們是不享元的,他們是三個不同的例項,也就是說他們不共享一個儲存空間,我們今天所說的享元是這樣
class Program { static void Main(string[] args) { int extrinsicstate = 0; FlyweightFactory f = FlyweightFactory.getFactory(); Flyweight fx = f.GetFlyweight("X"); fx.Operation(++extrinsicstate); Flyweight fy = f.GetFlyweight("X"); fy.Operation(++extrinsicstate); Flyweight fz = f.GetFlyweight("X"); fz.Operation(++extrinsicstate); Console.Read(); } }
這樣我們獲取到的才是同一個例項,這樣fx、fy、fz三個物件才實現了享元,因為他們共用一個儲存空間。好了,今天的享元模式就講完了
享元模式:運用共享技術有效的支援大量細粒度物件的複用。系統只適用少量的物件,而這些物件都很相似,狀態變化很小,可以實現物件的多次複用。