設計模式(15)---享元模式

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();
        }
    }
View Code

運行結果:對象

 

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());
View Code

 

4、優缺點及適用場景

優勢:

下降了系統中對象的數量,從而下降了系統中細粒度對象給內存帶來的壓力。

缺點:

1)爲了使對象能夠共享,須要將對象的一些狀態外部化,增長了系統複雜度

2)將享元對象狀態外部化,使得讀取外部狀態的運行時間稍微變長。

 

適用場景:

系統中須要大量的細粒度對象,同時這些對象耗費大量的內存,而且對象的狀態大部分能夠外部化,此時使用享元模式是沒有錯的。

相關文章
相關標籤/搜索