享元模式(Flyweight),運用共享技術有效地支持大量細粒度的對象。javascript
下面給出享元模式的結構圖:html
下面給出享元模式的基本代碼結構:java
namespace ConsoleApplication1 { //Flyweight類,它是全部具體享元類的超類或接口,經過這個接口,Flyweight能夠接受並做用於外部狀態 abstract class Flyweight { public abstract void Operation(int extrinsicstate); } //ConcreteFlyweight是繼承Flyweight或實現Flyweight接口,併爲內部狀態增長存儲空間 class ConcreteFlyweight : Flyweight { public override void Operation(int extrinsicstate) { Console.WriteLine("具體Flyweight:" + extrinsicstate); } } //UnsharedConcreteFlyweight是指那些不須要共享的Flyweight子類。由於Flyweight接口共享稱爲可能,但它並不強制共享 class UnsharedConcreteFlyweight : Flyweight { public override void Operation(int extrinsicstate) { Console.WriteLine("不共享的具體Flyweight:" + extrinsicstate); } } //FlyweightFactory,是一個享元工廠,用來建立並管理Flyweight對象。它主要是用來確保合理地共享Flyweight //當用戶請求一個Flyweight時,FlyweightFactory對象提供一個已建立的實例,如不存在則建立一個。 class FlyweightFactory { private Hashtable flyweights = new Hashtable(); public FlyweightFactory() //初始化工廠,先生成3個實例 { flyweights.Add("X", new ConcreteFlyweight()); flyweights.Add("Y", new ConcreteFlyweight()); flyweights.Add("Z", new ConcreteFlyweight()); } public Flyweight GetFlyweight(string key) //根據客戶端請求,得到已生成實例 { return ((Flyweight)flyweights[key]); } } class Program { static void Main(string[] args) { int extrinsicstate = 22; //代碼外部狀態 FlyweightFactory f = new FlyweightFactory(); Flyweight fx = f.GetFlyweight("X"); fx.Operation(--extrinsicstate); Flyweight fy = f.GetFlyweight("Y"); fx.Operation(--extrinsicstate); Flyweight fz = f.GetFlyweight("Z"); fx.Operation(--extrinsicstate); Flyweight uf = new UnsharedConcreteFlyweight(); uf.Operation(--extrinsicstate); Console.ReadKey(); } } }
結果如圖所示:git
UnsharedConcreteFlyweight用於解決那些不須要共享對象的問題。由於享元模式在使用的時候,既有須要共享的部分也有不須要共享的部分,此時UnsharedConcreteFlyweight的做用就出來了。設計模式
享元模式能夠避免大量很是類似類的開銷。在程序設計中,有時須要生成大量細粒度的類實例來表示數據。若是能發現這些實例除了幾個參數外基本上都是相同的,有時就可以受大幅地減小須要實例化的類的數量。若是能把那些參數移到類實例的外面,在方法調用時將他們傳遞進來,就能夠經過共享大幅度地減小單個實例的數目。ide
在現實中何時才應該考慮使用享元模式呢?post
若是一個應用程序使用了大量的對象,而大量的這些對象形成了很大的存儲開銷時就應該考慮使用;還有就是對象的大多數狀態能夠外部狀態,若是刪除對象的外部狀態,那麼能夠用相對較少的共享對象取代不少組對象,此時能夠考慮使用享元模式。學習
下面回到《大話設計模式》裏面的網站建設的例子:網站
namespace ConsoleApplication1 { //用戶 public class User { private string name; public User(string name) { this.name = name; } public string Name { get { return name; } } } //網站抽象類 abstract class WebSite { public abstract void Use(User user); //"使用"方法須要傳遞"用戶"對象 } //具體網站類 class ConcreteWebSite : WebSite { private string name = ""; public ConcreteWebSite(string name) { this.name = name; } public override void Use(User user) //實現"Use"方法 { Console.WriteLine("網站分類:" + name + " 用戶:" + user.Name); } } //網站工廠類 class WebSiteFactory { private Hashtable flyweights = new Hashtable(); //得到網站分類 public WebSite GetWebSiteCategory(string key) { if (!flyweights.ContainsKey(key)) { flyweights.Add(key, new ConcreteWebSite(key)); } return ((WebSite)flyweights[key]); } //得到網站分類總數 public int GetWebSiteCount() { return flyweights.Count; } } class Program { static void Main(string[] args) { WebSiteFactory f = new WebSiteFactory(); WebSite ws1 = f.GetWebSiteCategory("產品展現"); ws1.Use(new User("小菜")); WebSite ws2 = f.GetWebSiteCategory("產品展現"); ws1.Use(new User("大鳥")); WebSite ws3 = f.GetWebSiteCategory("產品展現"); ws1.Use(new User("嬌嬌")); WebSite ws4 = f.GetWebSiteCategory("博客"); ws1.Use(new User("關羽")); WebSite ws5 = f.GetWebSiteCategory("博客"); ws1.Use(new User("張飛")); WebSite ws6 = f.GetWebSiteCategory("博客"); ws1.Use(new User("趙雲")); Console.WriteLine("獲得網站分類的總數爲{0}",f.GetWebSiteCount()); Console.ReadKey(); } } }
結果以下圖所示:this