設計模式之-享元模式

定義:

享元模式(Flyweight Pattern):運用共享技術有效地支持大量細粒度對象的複用。系統只使用少許的對象,而這些對象都很類似,狀態變化很小,能夠實現對象的屢次複用。因爲享元模式要求可以共享的對象必須是細粒度對象,所以它又稱爲輕量級模式,它是一種對象結構型模式。git

享元模式參與者

  • Flyweight:全部具體享元類的超類或接口,經過這個超類或接口,Flyweight能夠接受並做用於外部狀態。
  • FlyweightFactory:享元工廠,用來建立並管理Flyweight,當用戶請求一個Flyweight時,FlyweightFactory提供一個已建立的實例或者建立一個(若是不存在)。
  • ConcreteFlyweight:繼承Flyweight超類或實現Flyweight接口。
  • UnsharedConcreteFlyweight:指那些不須要共享的Flyweight子類。

享元模式基本代碼

Flyweight類:github

namespace FlyweightPattern.BasicStructure
{
    abstract class Flyweight
    {
        public abstract void Operation(int extrinsicState);
    }
}

ConcreteFlyweight類:web

namespace FlyweightPattern.BasicStructure
{
    class ConcreteFlyweight : Flyweight
    {
        public override void Operation(int extrinsicState)
        {
            Console.WriteLine("具體Flyweight:" + extrinsicState);
        }
    }
}

UnSharedConcreteFlyweight類:編程

namespace FlyweightPattern.BasicStructure
{
    class UnSharedConcreteFlyweight : Flyweight
    {
        public override void Operation(int extrinsicState)
        {
            Console.WriteLine("不共享的具體Flyweight:" + extrinsicState);
        }
    }
}

FlyweightFactory類:ide

namespace FlyweightPattern.BasicStructure
{
    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];
        }
    }
}

客戶端調用代碼:網站

static void Main(string[] args)
    {
        try
        {
            {//BasicStructure
                int extrinsicState = 22;
                FlyweightFactory flyweightFactory = new FlyweightFactory();
                var flyweight = flyweightFactory.GetFlyweight("X");
                flyweight.Operation(--extrinsicState);

                flyweight = flyweightFactory.GetFlyweight("Y");
                flyweight.Operation(--extrinsicState);

                flyweight = flyweightFactory.GetFlyweight("Z");
                flyweight.Operation(--extrinsicState);

                UnSharedConcreteFlyweight uf = new UnSharedConcreteFlyweight();
                uf.Operation(--extrinsicState);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        Console.ReadKey();
    }

結果以下:this

用外觀模式實現網站共享代碼

場景模擬:因爲多個客戶須要作網站,其中有一些客戶的網站是基本同樣的,只有數據不同。spa

WebSite(網站抽象)類——Flyweight類code

namespace FlyweightPattern.SituationSimulation
{
    /// <summary>
    /// 網站抽象類
    /// </summary>
    abstract class WebSite
    {
        public abstract void Use();
    }
}

ConcreteWebSite(具體網站)類——ConcreteFlyweight類對象

namespace FlyweightPattern.SituationSimulation
{
    /// <summary>
    /// 具體網站類
    /// </summary>
    class ConcreteWebSite : WebSite
    {
        public string Name { get; }
        public ConcreteWebSite(string name)
        {
            this.Name = name;
        }
        public override void Use()
        {
            Console.WriteLine("網站分類:" + Name);
        }
    }
}

WebSiteFactory(網站工廠)類——FlyweightFactory類

namespace FlyweightPattern.SituationSimulation
{
    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;
        }
    }
}

客戶端調用代碼:

static void Main(string[] args)
    {
        try
        {
            {//SituationSimulation
                WebSiteFactory webSiteFactory = new WebSiteFactory();
                var fx = webSiteFactory.GetWebSiteCategory("產品展現");
                fx.Use();
                var fy = webSiteFactory.GetWebSiteCategory("產品展現");
                fy.Use();
                var fz = webSiteFactory.GetWebSiteCategory("產品展現");
                fz.Use();
                var fl = webSiteFactory.GetWebSiteCategory("博客");
                fl.Use();
                var fm = webSiteFactory.GetWebSiteCategory("博客");
                fm.Use();
                var fn = webSiteFactory.GetWebSiteCategory("博客");
                fn.Use();

                Console.WriteLine($"網站分類總數爲:{webSiteFactory.GetWebSiteCount()}");
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        Console.ReadKey();
    }

結果以下:

優勢:

享元模式的優勢

  • 享元模式的優勢在於它能夠極大減小內存中對象的數量,使得相同對象或類似對象在內存中只保存一份。
  • 享元模式的外部狀態相對獨立,並且不會影響其內部狀態,從而使得享元對象能夠在不一樣的環境中被共享。

缺點:

享元模式的缺點

  • 享元模式使得系統更加複雜,須要分離出內部狀態和外部狀態,這使得程序的邏輯複雜化。
  • 爲了使對象能夠共享,享元模式須要將享元對象的狀態外部化,而讀取外部狀態使得運行時間變長。

適用環境:

在如下狀況下可使用享元模式:

  • 一個系統有大量相同或者類似的對象,因爲這類對象的大量使用,形成內存的大量耗費。
  • 對象的大部分狀態均可之外部化,能夠將這些外部狀態傳入對象中。
  • 使用享元模式須要維護一個存儲享元對象的享元池,而這須要耗費資源,所以,應當在屢次重複使用享元對象時才值得使用享元模式。

總結:

  • 享元模式運用共享技術有效地支持大量細粒度對象的複用。系統只使用少許的對象,而這些對象都很類似,狀態變化很小,能夠實現對象的屢次複用,它是一種對象結構型模式。
  • 享元模式包含四個角色:抽象享元類聲明一個接口,經過它能夠接受並做用於外部狀態;具體享元類實現了抽象享元接口,其實例稱爲享元對象;非共享具體享元是不能被共享的抽象享元類的子類;享元工廠類用於建立並管理享元對象,它針對抽象享元類編程,將各類類型的具體享元對象存儲在一個享元池中。
  • 享元模式以共享的方式高效地支持大量的細粒度對象,享元對象能作到共享的關鍵是區份內部狀態和外部狀態。其中內部狀態是存儲在享元對象內部而且不會隨環境改變而改變的狀態,所以內部狀態能夠共享;外部狀態是隨環境改變而改變的、不能夠共享的狀態。
  • 享元模式主要優勢在於它能夠極大減小內存中對象的數量,使得相同對象或類似對象在內存中只保存一份;其缺點是使得系統更加複雜,而且須要將享元對象的狀態外部化,而讀取外部狀態使得運行時間變長。
  • 享元模式適用狀況包括:一個系統有大量相同或者類似的對象,因爲這類對象的大量使用,形成內存的大量耗費;對象的大部分狀態均可之外部化,能夠將這些外部狀態傳入對象中;屢次重複使用享元對象。

 

源代碼地址:https://github.com/houzhenhuang/DesignPattern

相關文章
相關標籤/搜索