1. 程式人生 > >通俗易懂設計模式解析——享元模式

通俗易懂設計模式解析——享元模式

前言

   今天我們繼續講述設計模式,今天提及的是享元模式,享——共享。之前不是出現了一系列共享的東西嗎?為啥呀,還不就是有些東西每個人都需要,但是每個人都去買一個又有點浪費。所以出現共享。話費一定的經濟可以使用,使用完成之後又歸還。這就是享。分享共享。今天講的享元模式跟這相類似。享元模式——通俗來說也就是共享最小單元的一種模式。我們就一起看看到底啥是這享元模式吧。

享元模式介紹

一、來由

  在軟體系統開發中,我們肯定會出現重複使用同一個物件的情況,每次使用都new一個物件出來。這樣的話對於記憶體來說就需要多次反覆的申請記憶體了。這樣使用記憶體也就越來越多,這會出現大問題的。那麼能不能建立new一個物件。然後使用的時候就共同使用一個就好了。這也就是享元模式的含義所在了——共享一個物件。

二、 意圖

  運用共享技術有效地支援大量細粒度的物件。

三、 案例圖

 

 

 

 

四、享元模式程式碼示例

   看上面的案例圖我們可以發現享元模式主要包含以下部分:

享元工廠角色:這個角色主要負責建立和管理享元角色。判斷是否存在符合要求的享元物件,如果存在則直接拿取,如果不存在的話就會建立一個享元物件並儲存。

抽象享元角色:這個角色是所有享元角色的基類。提供需要實現的公共介面

具體享元角色:繼承於抽象享元角色。實現其抽象的介面。

客戶端:負責呼叫並處理邏輯,且儲存多有享元物件的狀態

  在我們平時使用的編輯器中,會出現很多的字,這些字也是會一直重複出現的。那麼我們現在就試著使用享元模式來對這些字進行處理。這裡暫且使用字母代替:

 

namespace Flyweight_Pattern
{
    class FlyweightPattern
    {
    }

    #region 抽象享元角色——抽象公共介面
    public abstract class Flyweight 
    {
        /// <summary>
        /// 表述輸出的位置
        /// </summary>
        /// <param name="externalstate">外在的狀態,隨著環境改變而改變</param>
        public abstract void OutInput(int externalstate);
    }
    #endregion

    #region 具體享元角色——實現其具體
    public class SpecificFlyweight : Flyweight
    {
        private string Innerstate;
        /// <summary>
        /// 內部狀態接收
        /// </summary>
        /// <param name="innerstate">內部狀態</param>
        public SpecificFlyweight(string innerstate) 
        {
            this.Innerstate = innerstate;
        }
        /// <summary>
        /// 實現方法
        /// </summary>
        /// <param name="externalstate">外部狀態</param>
        public override void OutInput(int externalstate)
        {
            Console.WriteLine($"內部狀態:{Innerstate}————外部狀態:{externalstate}");
        }
    }
    #endregion

    #region 享元工廠角色——對享元角色進行建立及管理的
    public class FlyweightFactory 
    {
        public Dictionary<string, SpecificFlyweight> keyValuePairs = new Dictionary<string, SpecificFlyweight>();

        public SpecificFlyweight GetFlyweight(string Key) 
        {
            SpecificFlyweight specific = null;
            if (!keyValuePairs.ContainsKey("A"))
            {
                Console.WriteLine("暫時未遇見該Key");
                keyValuePairs.Add(Key, new SpecificFlyweight(Key));
                Console.WriteLine("現已儲存該Key"); 
            }
            else
            {
                 specific = keyValuePairs[Key] as SpecificFlyweight;
            }
            return specific;
        }
    }
    #endregion
}

 

namespace Flyweight_Pattern
{
    class Program
    {
        static void Main(string[] args)
        {

            ///初始化享元工廠
            FlyweightFactory factory = new FlyweightFactory();
            while (true)
            {
                Console.WriteLine("請輸入字元的位置:");
                var indexstring = Console.ReadLine();
                if (int.TryParse(indexstring, out int index))
                {
                    Console.WriteLine("請輸入字元:");
                    string str = Console.ReadLine();

                    ///判斷字元是否建立
                    Flyweight flyweight = factory.GetFlyweight(str);

                    //如果存在則輸出資訊
                    if (flyweight != null)
                    {
                        flyweight.OutInput(index);
                    }
                }
                else
                {
                    Console.WriteLine("請輸入數字!");
                }
                Console.WriteLine("結束請輸入N");
                if (Console.ReadLine()=="N")
                {
                    break;
                }
            }

            Console.WriteLine("已結束");
            Console.ReadLine();
        }
    }
}

 

使用場景及優缺點

  這裡我們需要注意的是劃分好外部狀態和內部狀態,否則混淆之後可能引起執行緒安全問題。同時必不可少的是一個工廠物件進行控制。

這裡我們解釋下在享元模式中的內在狀態和外在狀態:

內在狀態:不隨環境的變化而變化,上面例子中不管位置如何變化,A就是A。字母A就是內在狀態。

外在狀態:會隨著環境的變化而變化,上面例子中位置變化所以輸出的位置也是不一致的。字母A的位置就是外在狀態

一、 使用場景

  對於享元模式來說其使用場景可分以下四點:

1、系統需要大量相似物件

2、建立這些物件需要花費大量資源

3、狀態可分為內在狀態和外在狀態,可以根據內在狀態分為各種組。

4、需要緩衝池的場景

二、 優點

1、享元模式的優點最主要的是極大的減少了系統中物件的建立,降低了記憶體使用提高了效率

三、 缺點

任何東西來說都是有利有弊的,我們看下享元模式又存在哪些弊端呢

1、為了使一些物件共享,對物件區分了內在狀態和外在狀態,使系統邏輯變為複雜了,使系統更加難於理解了。

總結

  今天的享元模式就暫時介紹的這麼多,享元模式精髓也就是達到物件的共享,達到共享的話就需要抽出一部分東西達到相似。所以這又區分了內在狀態和外在狀態。內在狀態不隨環境變化而變化,屬於可共享的。而外在狀態隨著環境改變而改變,所以不能共享的。在.Net開發中,我們經常使用到的額String型別的實現就採用了享元模式的設計。在string中具有相同字元序列的String物件不會重複建立。具體細節想要研究的可以自行查詢資料。在我們使用設計模式的時候有一些點還是需要多次強調及注意的。基於原則設計。視情況採用設計模式。不要為了使用設計模式而去使用設計模式。一切都是為了重用程式碼、讓程式碼更容易被他人理解、保證程式碼可靠性。

  勇敢的面對不一定成功,但你不面對就一定不成功。

    C#設計模式系列目錄

歡迎大家掃描下方二維碼,和我一起踏上設計模式的闖關之路吧!