A: 三個做品展現,三個博客,其實它們本質上都是同樣的代碼。
B: 共用一套代碼,可是畢竟是不一樣的網站,數據都不相同。
A: 共享代碼,爲何不能夠呢?好比如今大型的網站,裏面的一個博客或商家也能夠理解爲一個個小的網站,但它們是如何作的?
B: 利用ID的不一樣,來區分不一樣的用戶,具體數據和模版都是不一樣,可是代碼核心和數據庫倒是共享的。數據庫
運用共享技術有效的支持大量細粒度的對象。
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"); fy.Operation(--extrinsicstate); Flyweight fz = f.GetFlyweight("Z"); fz.Operation(--extrinsicstate); UnsharedConcreteFlyweight uf = new UnsharedConcreteFlyweight(); uf.Operation(--extrinsicstate); Console.Read(); } } 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 Flyweight GetFlyweight(string key) { return ((Flyweight)flyweights[key]); } } abstract class Flyweight { public abstract void Operation(int extrinsicstate); } 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); } }
B: FlyweightFactory根據客戶需求返回早已生成好的對象,但必定要事先生成對象實例嗎?
A: 其實是不必定須要,徹底能夠初始化時什麼都不作,到須要時,再去判斷對象是否爲null來決定是否實例化。
A: UnsharedConcreteFlyweight子類解決那些不須要共享對象的問題。設計模式
class Program { static void Main(string[] args) { WebSiteFactory f = new WebSiteFactory(); WebSite fx = f.GetWebSiteCategory("產品展現"); fx.Use(); WebSite fy = f.GetWebSiteCategory("產品展現"); fy.Use(); WebSite fz = f.GetWebSiteCategory("產品展現"); fz.Use(); WebSite fl = f.GetWebSiteCategory("博客"); fl.Use(); WebSite fm = f.GetWebSiteCategory("博客"); fm.Use(); WebSite fn = f.GetWebSiteCategory("博客"); fn.Use(); Console.WriteLine("網站分類總數爲 {0}", f.GetWebSiteCount()); Console.Read(); } } //網站工廠 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; } } //網站 abstract class WebSite { public abstract void Use(); } //具體的網站 class ConcreteWebSite : WebSite { private string name = ""; public ConcreteWebSite(string name) { this.name = name; } public override void Use() { Console.WriteLine("網站分類:" + name); } }
A: 這樣有個問題,你給企業建的網站不是一家的企業,它們的數據不會相同,全部至少它們都應該有不一樣的賬號,你怎麼辦?
B: 時間上,上面的代碼沒有體現對象間的不一樣,只體現了它們的共享部分。數組
A: 在享元對象內部而且不會隨環境改變而改變的共享部分,能夠稱爲享元對象的內部狀態,而隨着環境改變而改變,不能夠共享的就是外部狀態。事實上,享元模式能夠避免大量很是類似類的開銷。在程序設計中,有時須要生成大量細粒度的類實例來表示數據。若是能發現這些實例除了幾個參數外基本相同,有時可以大幅度的減小須要實例化的類的數量。若是能把那些參數移到類實例外面,在方法調用將它們傳遞進來,就能夠經過共享大幅度地減小單個實例的數目。內部狀態存儲於ConcreteFlyweight對象之中,而外部對象則應該考慮有客戶端對象存儲或計算,當調用Flyweight對象的操做時,將該狀態傳遞給它。
B: 那你的意識是說,客戶的帳號是外部狀態,應該由專門的對象來處理。
ide
class Program { static void Main(string[] args) { WebSiteFactory f = new WebSiteFactory(); WebSite fx = f.GetWebSiteCategory("產品展現"); fx.Use(new User("小菜")); WebSite fy = f.GetWebSiteCategory("產品展現"); fy.Use(new User("大鳥")); WebSite fz = f.GetWebSiteCategory("產品展現"); fz.Use(new User("嬌嬌")); WebSite fl = f.GetWebSiteCategory("博客"); fl.Use(new User("老頑童")); WebSite fm = f.GetWebSiteCategory("博客"); fm.Use(new User("桃谷六仙")); WebSite fn = f.GetWebSiteCategory("博客"); fn.Use(new User("南海鱷神")); Console.WriteLine("獲得網站分類總數爲 {0}", f.GetWebSiteCount()); //string titleA = "大話設計模式"; //string titleB = "大話設計模式"; //Console.WriteLine(Object.ReferenceEquals(titleA, titleB)); Console.Read(); } } //用戶 public class User { private string name; public User(string name) { this.name = name; } public string Name { get { return 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; } } //網站 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("網站分類:" + name + " 用戶:" + user.Name); } }
A: 若是一個應用程序使用了大量的對象,而大量的這些對象形成了很大的開銷時就應該考慮使用,還有就是對象的大多數狀態能夠外部狀態,若是刪除對象的外部狀態,那麼能夠用相對較小的共享對象取代不少組對象,此時能夠考慮使用享元模式。
A: 雖然說享元模式更多的時候是一種底層的設計模式(數組,字符串共享),但現實也是有應用的。好比說休閒遊戲開放,想圍棋,五子棋等,它們都有大量的棋子對象,它們的內部狀態和外部狀態?
B: 顏色是內部狀態和座標是棋子的外部狀態。
A: 享元模式須要維護一個記錄了系統已有的全部享元列表,而這自己須要耗費資源,另外享元模式使得系統更加複雜。爲了使對象能夠共享,須要將一些狀態外部化,這使得程序的邏輯複雜化。所以,應當在有足夠的對象實例可工共享時才值得使用享元模式。網站