1. 程式人生 > 其它 >設計模式之---享元模式

設計模式之---享元模式

享元模式(Flyweight),運用共享技術有效的支援大量細粒度的物件。

什麼時候使用享元模式

如果一個應用程式使用了大量的物件,而大量的這些物件造成了很大的儲存開銷時就可以考慮使用;還有就是物件的大多數狀態可以外部狀態,如果刪除物件的外部狀態,那麼可以用相對較少的共享物件取代很多組物件,此時可以考慮使用享元模式。

歸納享元模式的好處?

用了享元模式,所以有了共享物件,例項總數就打打減少了,如果共享的物件越多,儲存節約的也就越多,節約量隨著共享狀態的增多而增多。

            string titlea = "yxz";
            string titleb = "yxz
"; Console.WriteLine(object.ReferenceEquals(titleb, titlea));

基本程式碼如下:

客戶端程式碼

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

後臺

    abstract class Flyweight
    {
        public abstract void Operation(int extrinsicsstate);
    }
    class ConcreteFlyweight : Flyweight
    {
        public override void Operation(int extrinsicsstate)
        {
            Console.WriteLine("具體Flyweight:" + extrinsicsstate);
        }
    }

    class UnsharedConcreteFlyweight : Flyweight
    {
        public override void Operation(int extrinsicsstate)
        {
            Console.WriteLine("不共享的具體Flyweight:" + extrinsicsstate);
        }
    }
    class FlyweightFactory                                                  //享元工廠,用來建立並管理Flyweight物件。它主要用來確保合理的共享Flyweight
    {
        private Hashtable flyweight = new Hashtable();
        public FlyweightFactory()                                           //初始化工廠時,先生成三個例項
        {
            flyweight.Add("X", new ConcreteFlyweight());
            flyweight.Add("Y", new ConcreteFlyweight());
            flyweight.Add("Z", new ConcreteFlyweight());
        }
        public Flyweight GetFlyweight(string key)                           //根據客戶端請求,獲得已生成的例項
        {
            return ((Flyweight)flyweight[key]);
        }
    }
View Code

UML類圖

內部狀態和外部狀態

在享元物件內部並且不會隨環境改變而改變的共享部分,稱為享元物件的內部狀態。隨著環境改變而改變的,不可以共享的狀態就是外部狀態了。

享元模式可以避免大量非常相似類的開銷。

在程式設計中,有時需要生成大量細粒度的類例項來表示資料。如果能發現這些例項除了引數外基本都是相同的,有時就能夠大幅度的減少需要例項化的類的數量。如果能把那些引數轉移到類例項的外面,在方法呼叫時將它們傳遞進來,就可以共享大幅度的減少單個例項的數目。

            WebSiteFactory f = new WebSiteFactory();
            WebSite fx = f.GetWebsiteCategory("產品展示");
            fx.Use(new User("小菜"));

            WebSite fy = f.GetWebsiteCategory("產品展示");
            fx.Use(new User("大鳥"));

            WebSite fz = f.GetWebsiteCategory("產品展示");
            fx.Use(new User("小鳥"));
            WebSite fr = f.GetWebsiteCategory("產品");
            fx.Use(new User("小鳥"));
            Console.WriteLine("得到網站的分類總數:{0}", f.GetWebSiteCount());

            Console.Read();
View Code
    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 = string.Empty;
        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;
        }
    }
View Code