1、定義web
享元模式:運用共享技術有效地支持大量細粒度的對象。ide
解釋:須要大量重複new一個對象時,使用享元模式可讓你減小對象的初始化,從而減少內存開銷。太蒼白了,理解的不到位,但願本身之後補充吧。函數
補充:當一個對象的狀態可在外部初始化,同時系統中須要大量重複建立該對象時,享元模式在建立對象的工廠方法中使用一個哈希表,用於保存其外部化狀態和對象自己。在系統中,使用對象時首先判斷其是否存在,存在則拿來直接使用,不存在須要從新建立並保存到哈希表中。網站
2、UML類圖及基本代碼this
基本代碼:spa
public abstract class Flyweight { public abstract void Operation(int extrinsicstate); } public class ConcreteFlyweight : Flyweight { // 內部狀態 private string intrinsicstate; // 構造函數 public ConcreteFlyweight(string innerState) { this.intrinsicstate = innerState; } /// <summary> /// 享元類的實例方法 /// </summary> /// <param name="extrinsicstate">外部狀態</param> public override void Operation(int extrinsicstate) { Console.WriteLine("具體實現類: intrinsicstate {0}, extrinsicstate {1}", intrinsicstate, extrinsicstate); } } public class FlyweightFactory { // 最好使用泛型Dictionary<string,Flyweighy> //public Dictionary<string, Flyweight> flyweights = new Dictionary<string, Flyweight>(); public Hashtable flyweights = new Hashtable(); public FlyweightFactory() { flyweights.Add("A", new ConcreteFlyweight("A")); flyweights.Add("B", new ConcreteFlyweight("B")); flyweights.Add("C", new ConcreteFlyweight("C")); } public Flyweight GetFlyweight(string key) { // 更好的實現以下 //Flyweight flyweight = flyweights[key] as Flyweight; //if (flyweight == null) //{ // Console.WriteLine("駐留池中不存在字符串" + key); // flyweight = new ConcreteFlyweight(key); //} //return flyweight; return flyweights[key] as Flyweight; } }
客戶端調用:code
class Program { static void Main(string[] args) { // 定義外部狀態,例如字母的位置等信息 int externalstate = 10; // 初始化享元工廠 FlyweightFactory factory = new FlyweightFactory(); // 判斷是否已經建立了字母A,若是已經建立就直接使用建立的對象A Flyweight fa = factory.GetFlyweight("A"); if (fa != null) { // 把外部狀態做爲享元對象的方法調用參數 fa.Operation(--externalstate); } // 判斷是否已經建立了字母B Flyweight fb = factory.GetFlyweight("B"); if (fb != null) { fb.Operation(--externalstate); } // 判斷是否已經建立了字母D Flyweight fd = factory.GetFlyweight("D"); if (fd != null) { fd.Operation(--externalstate); } else { Console.WriteLine("駐留池中不存在字符串D"); // 這時候就須要建立一個對象並放入駐留池中 ConcreteFlyweight d = new ConcreteFlyweight("D"); factory.flyweights.Add("D", d); } Console.Read(); } }
運行結果:對象
3、具體實例:blog
構建一個由不一樣用戶使用的通用網站,具體代碼以下:內存
public class User { private string name; public string Name { get { return name; } } public User(string name) { this.name = 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) { Console.WriteLine("website type:" + name + "user:" + 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; } }
客戶端調用:
WebsiteFactory wf = new WebsiteFactory(); Website wx = wf.GetWebsiteCategory("show"); wx.Use(new User("a")); Website wy = wf.GetWebsiteCategory("show"); wy.Use(new User("b")); Website wz = wf.GetWebsiteCategory("see"); wz.Use(new User("c")); Console.WriteLine("website type num:" + wf.GetWebsiteCount());
4、優缺點及適用場景
優勢:
下降了系統中對象的數量,從而下降了系統中細粒度對象給內存帶來的壓力。
缺點:
1)爲了使對象能夠共享,須要將對象的一些狀態外部化,增長了系統複雜度
2)將享元對象狀態外部化,使得讀取外部狀態的運行時間稍微變長。
適用場景:
系統中須要大量的細粒度對象,同時這些對象耗費大量的內存,而且對象的狀態大部分能夠外部化,此時使用享元模式是沒有錯的。