設計模式之享元模式

名詞解釋: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這個外部狀態對象,因此就能夠把內部狀態與外部狀態很好的結合。

 

總結:

 若是一個應用程序使用了大量的對象,而大量的對象形成了很大的存儲開銷時就應該考慮使用享元模式;對象的大多數狀態能夠外部狀態,若是刪除對象的外部狀態,那麼能夠用相對較少的共享對象取代不少組對象,此時能夠考慮使用享元對象。在實際應用中,使用了享元模式實例總數就大大減小了。

相關文章
相關標籤/搜索