名詞解釋:ide
享元模式(Flyweight):運用共享技術有效地支持大量細粒度的對象。函數
必要元素:網站
1.一個享元工廠,用來建立並管理Flyweight對象。它主要是用來確保合理地共享Flyweight,當用戶請求一個Flyweight時,FlyweightFactory對象提供一個已建立的實例或者建立一個(若是不存在);
2.全部具體享元類的父類或接口,經過這個接口,Flyweight能夠接受並做用於外部狀態;
3.繼承Flyweight父類或者實現Flyweight接口,併爲內部狀態增長存儲空間;
4.指那些不須要共享的Flyweight子類,由於Flyweight接口共享成爲可能,可是並不強制共享(即那些不能共享的部分)。this
上例子:spa
Flyweight享元抽象類:設計
abstract class Flyweight { public abstract void Operation(int extrinsicstate); }
Flyweight具體共享類:code
class ConcreteFlyweight:Flyweight { public override void Operation(int extrinsicstate) { Console.WriteLine("具體Flyweight:"+extrinsicstate); } } class UnsharedConcreteFlyweight:Flyweight { public override void Operation(int extrinsicstate) { Console.WriteLine("不共享的具體Flyweight:"+extrinsicstate); } }
享元工廠:對象
class FlyweightFactory { private Dictionary<string, Flyweight> flyweights = new Dictionary<string, Flyweight>(); public FlyweightFactory() { flyweights.Add("X", new ConcreteFlyweight()); flyweights.Add("Y", new ConcreteFlyweight()); flyweights.Add("Z", new ConcreteFlyweight()); } public Flyweight GetFlyweight(string key) { return (Flyweight)flyweights[key]; } }
調用:blog
//外部狀態 int extrinsicstate = 22; FlyweightFactory factory = new FlyweightFactory(); Flyweight fx = factory.GetFlyweight("X"); fx.Operation(--extrinsicstate); Flyweight fy = factory.GetFlyweight("Y"); fx.Operation(--extrinsicstate); Flyweight fz = factory.GetFlyweight("Z"); fz.Operation(--extrinsicstate); Flyweight uf = new UnsharedConcreteFlyweight(); uf.Operation(--extrinsicstate); Console.Read();
經過享元類父類和子類(共享和非共享部分)以及享元類工廠,構成了享元模式,這樣在使用的時候就不會建立屢次對象,有效的利用資源。繼承
例子2(假設有一個網站類,而網站有不少種類型):
抽象類:
/// <summary> /// 網站抽象類 /// </summary> abstract class WebSite { public abstract void Use(); }
具體網站類:
/// <summary> /// 具體網站類 /// </summary> class ConcreteWebSite:WebSite { private string name = ""; public ConcreteWebSite(string name) { this.name = name; } public override void Use() { Console.WriteLine("網站分類:"+name); } }
網站工廠類:
/// <summary> /// 網站工廠 /// </summary> class WebSiteFactory { private Dictionary<string, WebSite> flyweights = new Dictionary<string, WebSite>(); /// <summary> /// 得到網站分類 /// </summary> /// <param name="key"></param> /// <returns></returns> public WebSite GetWebSite(string key) { if (!flyweights.ContainsKey(key)) { flyweights.Add(key, new ConcreteWebSite(key)); } return flyweights[key]; } public int GetWebSiteCount() { return flyweights.Count; } }
使用:
WebSiteFactory factory = new WebSiteFactory(); WebSite fx = factory.GetWebSite("產品展現"); fx.Use(); WebSite fy = factory.GetWebSite("產品展現"); fy.Use(); WebSite fz = factory.GetWebSite("產品展現"); fz.Use(); WebSite fl = factory.GetWebSite("博客"); fl.Use(); WebSite fm = factory.GetWebSite("博客"); fm.Use(); WebSite fn = factory.GetWebSite("博客"); fn.Use(); Console.WriteLine("共有網站{0}個",factory.GetWebSiteCount()); Console.Read();
這樣設計基本實現了享元模式的共享對象的目的,也就是說無論建立幾個網站,只要是某一類型(博客或者其餘),都是徹底相同的,可是問題又來了,不一樣公司的網站應該有不一樣的帳號,因此咱們只是體現了共享的部分,還有非共享部分等待咱們實現。
實例2(集成非共享代碼):
外部狀態類(User類):
/// <summary> /// 用戶類(外部狀態) /// </summary> class User { private string name; public string Name { get { return name; } } public User(string name) { this.name = name; } }
抽象網站類:
/// <summary> /// 網站抽象類 /// </summary> abstract class WebSite { public abstract void Use(User user); }
方法增長了參數,參數爲外部狀態對象User。
具體網站類:
/// <summary> /// 具體網站類 /// </summary> class ConcreteWebSite:WebSite { private string name = ""; public ConcreteWebSite(string name) { this.name = name; } public override void Use(User user) { Console.WriteLine("網站分類:"+name+" 用戶:"+user.Name); } }
變化也是User函數添加User對象參數。
工廠:無變化。
使用:
WebSiteFactory factory = new WebSiteFactory(); WebSite fx = factory.GetWebSite("產品展現"); fx.Use(new User("Colors")); WebSite fy = factory.GetWebSite("產品展現"); fy.Use(new User("Blue")); WebSite fz = factory.GetWebSite("產品展現"); fz.Use(new User("Listen")); WebSite fl = factory.GetWebSite("博客"); fl.Use(new User("Colors.Blue")); WebSite fm = factory.GetWebSite("博客"); fm.Use(new User("Listen.Fly")); WebSite fn = factory.GetWebSite("博客"); fn.Use(new User("李莫愁")); Console.WriteLine("共有網站{0}個",factory.GetWebSiteCount()); Console.Read();
這樣雖然是同一個類型的網站,可是有了User這個外部狀態對象,因此就能夠把內部狀態與外部狀態很好的結合。
總結:
若是一個應用程序使用了大量的對象,而大量的對象形成了很大的存儲開銷時就應該考慮使用享元模式;對象的大多數狀態能夠外部狀態,若是刪除對象的外部狀態,那麼能夠用相對較少的共享對象取代不少組對象,此時能夠考慮使用享元對象。在實際應用中,使用了享元模式實例總數就大大減小了。