抽象工廠模式【C#】

示例代碼爲了儘量突顯設計模式的特徵,採用了極簡代碼。儘可能避免其餘代碼對理解設計模式產生干擾

定義

抽象工廠模式(Abstract Factory Pattern):提供一個建立一系列相關或相互依賴對象的接口,而無須指定它們具體的類。
簡而言之,就是抽象工廠模式,可使具體工廠同時具有建立多種產品的能力。好比接下來的示例代碼中,電腦工廠具有生產顯示器能力,同時還具有生產主機的能力。

結構導圖(引自劉偉老師的博客

clipboard.png


代碼

示例項目完整結構

產品代碼

  • 產品-顯示器

/// <summary>
    /// 抽象產品
    /// 抽象顯示器
    /// </summary>
    interface IDisplay
    {
        void Show();
    }
/// <summary>
    /// 具體產品
    /// 蘋果顯示器
    /// </summary>
    class AppleDisplay : IDisplay
    {
        public void Show()
        {
            Console.WriteLine("蘋果顯示器正常工做。");
        }
    }
/// <summary>
    /// 具體產品
    /// 戴爾顯示器
    /// </summary>
    class DellDisplay : IDisplay
    {
        public void Show()
        {
            Console.WriteLine("戴爾顯示器正常工做。");
        }
    }
  • 產品-主機

/// <summary>
    /// 抽象產品
    /// 抽象主機
    /// </summary>
    interface IMainframe
    {
        void Open();
    }
/// <summary>
    /// 具體產品
    /// 蘋果主機
    /// </summary>
    class AppleMainframe : IMainframe
    {
        public void Open()
        {
            Console.WriteLine("蘋果主機成功開機。");
        }
    }
/// <summary>
    /// 具體產品
    /// 戴爾主機
    /// </summary>
    class DellMainframe : IMainframe
    {
        public void Open()
        {
            Console.WriteLine("戴爾主機成功開機。");
        }
    }

若是使用普通工廠模式,那麼每種產品,都應該存在其對應的工廠類,這樣就會致使該狀況下,要同時提供「顯示器工廠類」以及「主機工廠類」,後期添加了鍵盤,鼠標等產品後,還有再提供更多的對應的工廠類。這無疑會致使項目中的工廠數量過多,必定程度上會增長項目的複雜度。c#

此時,抽象工廠模式就派上用場了!設計模式

工廠代碼

/// <summary>
    /// 抽象工廠
    /// 電腦工廠
    /// </summary>
    interface IComputerFactory
    {
        /// <summary>
        /// 生產一個顯示器
        /// </summary>
        IDisplay ProduceADisplay();
    
        /// <summary>
        /// 生產一個主機
        /// </summary>
        IMainframe ProduceAMainframe();
    }
/// <summary>
    /// 具體工廠
    /// 蘋果電腦工廠
    /// </summary>
    class AppleComputerFactory : IComputerFactory
    {
        public IDisplay ProduceADisplay()
        {
            return new AppleDisplay();
        }
    
        public IMainframe ProduceAMainframe()
        {
            return new AppleMainframe();
        }
    }
/// <summary>
    /// 具體工廠
    /// 戴爾電腦工廠
    /// </summary>
    class DellComputerFactory : IComputerFactory
    {
        public IDisplay ProduceADisplay()
        {
            return new DellDisplay();
        }
    
        public IMainframe ProduceAMainframe()
        {
            return new DellMainframe();
        }
    }

此時,每一個電腦廠家,都有其獨立的工廠。客戶想要一臺電腦,只須要找指定廠家定製就足夠了。固然,實際上,你們買電腦通常不會直接找廠家,此處只是大概比喻。:Pide

請看客戶端代碼

class Program
    {
        static void Main(string[] args)
        {
            // 假設此時我想要一臺蘋果電腦
            // 建立蘋果電腦工廠
            var factory = new AppleComputerFactory();
    
            // 生產出顯示器並測試產品是否合格
            var display = factory.ProduceADisplay();
            display.Show();
    
            // 生產出主機並測試產品是否合格
            var mainframe = factory.ProduceAMainframe();
            mainframe.Open();
    
            // 完事
            Console.WriteLine("電腦生產完成,正在配送···");
        }
    }

以上。測試

運行結果

抽象工廠模式

補充討論

不少人說,後期若是拓展某個具體產品(好比如今只有蘋果和戴爾兩個品牌的電腦,後期可能添加華爲顯示器和華爲主機),很簡單,最多添加個具體工廠足矣。可是若是添加了某種產品(好比如今只有顯示器和主機,後期可能添加鍵盤等外設),那麼擴展起來將很是困難,由於想要擴展就須要改動現有抽象工廠。
而一旦對現有抽象工廠進行了改動(好比添加了生產鍵盤的方法),那麼全部繼承它的那些具體工廠,都須要同步改動(哪怕有些工廠從始至終也沒打算賣鍵盤,但它同樣須要跟着抽象工廠一塊兒被改造),這樣算起來,改動並不小。spa

但其實要我說的話,我不必定非要改動現有的抽象工廠。我能夠添加新的抽象工廠。.net

代碼以下:設計

/// <summary>
    /// 抽象工廠
    /// 附贈鍵盤的電腦工廠
    /// </summary>
    abstract class IComputerFactory_Keyboard : IComputerFactory
    {
        /// <summary>
        /// 持有舊工廠的引用
        /// </summary>
        protected abstract IComputerFactory OldComputerFactory { get; }

        /// <summary>
        /// 經過舊工廠生產顯示器
        /// </summary>
        public IDisplay ProduceADisplay()
        {
            return OldComputerFactory.ProduceADisplay();
        }

        /// <summary>
        /// 生產一個鍵盤
        /// </summary>
        public abstract IKeyboard ProduceAKeyboard();

        /// <summary>
        /// 經過舊工廠生產主機
        /// </summary>
        public IMainframe ProduceAMainframe()
        {
            return OldComputerFactory.ProduceAMainframe();
        }
    }

對應添加一個新的附贈鍵盤的工廠code

/// <summary>
    /// 具體工廠
    /// 戴爾新工廠-買電腦送鍵盤
    /// </summary>
    class DellComputerFactory_Keyboard : IComputerFactory_Keyboard
    {
        private readonly DellComputerFactory ComputerFactory = new DellComputerFactory();
        protected override IComputerFactory OldComputerFactory
        {
            get
            {
                return ComputerFactory;
            }
        }

        public override IKeyboard ProduceAKeyboard()
        {
            return new DellKeyboard();
        }
    }

如此這般,便可在不改動原工廠的狀況下,使指定廠商具有生產鍵盤的能力了。
PS:C#語言,還能夠經過擴展方法的方式,爲指定工廠添加一些額外的生產能力。對象

相關文章
相關標籤/搜索