面向對象的思想很好地解決了抽象性的問題,一般也不會出現性能上的問題。但是在某些情況下,對象的數量可能會太多,從而導致了運行時的代價。那麼我們如何去避免大量細粒度的對象,同時又不影響客戶程序使用面向對象的方式進行操作? 享元模式:運用共享技術有效的支持大量細粒度的對象 結構圖: 解釋: FlyweightFactory:一個享元工廠,用來創建並管理Flyweight對象,它主要是用來確保合理的共享Flyweight,當用戶請求一個Flyweight時,FlyweightFactory對象提供一個已創建的實例或者創建一個(如果不存在的話) Flyweight:所有具體享元類的超類或接口,通過這個接口,Flyweight尅接受並作用於外部狀態 ConcreteFlyweight:繼承Flyweight超累或實現Flyweight接口,並為內部狀態增加儲存空間 UnsharedConcreteFlyweight:指那些不需要共享的Flyweight子類,因為Flyweight接口共享成為可能,但它並不強制共享 代碼實現: [html] <span style="font-size:18px;">using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections; namespace 享元模式 { 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); Flyweight uf = new UnsharedConcreteFlyweight(); uf.Operation(--extrinsicstate); Console.Read(); } } //Flyweight 類,它是所有具體享元類的超類或接口 abstract class Flyweight { public abstract void Operation(int extrinsicstate); } //ConcreteFlyweight類,繼承Flyweight超類或實現Flyweight接口,並為內部狀態增加存儲空間 class ConcreteFlyweight : Flyweight { www.2cto.com public override void Operation(int extrinstate) { Console.WriteLine("具體Flyweight:" + extrinstate); } } //UnsharedConcreteFlyweight類,代表那些不需要共享的Flyweight子類 class UnsharedConcreteFlyweight : Flyweight { public override void Operation(int extrinsicstate) { Console.WriteLine("不共享的具體Flyweight:" + extrinsicstate); } } //FlyweightFactory類,是一個享元工廠,用來創建並管理Flyweight對象 class FlyweightFactory { //使用Hashtable需要調用using System.Collections; 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]); } } } </span> 例子:網站共享 結構圖: 代碼實現: [html] <span style="font-size:18px;">using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections; namespace 網站共享代碼 { 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 ()); Console.Read(); } } //用戶類 ,用於網站的客戶賬號,是“網站”類的外部狀態 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) { 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 ; } } } </span> 運行結果: 享元模式的應用 如果一個應用程序使用了大量的對象,而大量的這些對象造成了很大的存儲開銷時 當對象的大多數狀態可以外部狀態,如果刪除對象的外部狀態,那麼可以用相對較少的共享對象取代多組對象 享元模式的優點: 實例總數少了 共享的對象越多,存儲節約也就越多,節約量隨著共享狀態的增多而增大