抽象工廠模式(Abstract Factory Pattern):提供一個建立一系列相關或相互依賴對象的接口,而無須指定它們具體的類。
簡而言之,就是抽象工廠模式,可使具體工廠同時具有建立多種產品的能力。好比接下來的示例代碼中,電腦工廠具有生產顯示器能力,同時還具有生產主機的能力。
/// <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#語言,還能夠經過擴展方法的方式,爲指定工廠添加一些額外的生產能力。對象