設計模式(0)簡單工廠模式html
設計模式(2)工廠方法模式(Factory Method)github
源碼地址編程
抽象工廠模式通常的書面定義爲:提供一個建立一系列相關或相互依賴對象的接口,而無需指定他們具體的類設計模式
提供建立接口,無需指定具體實現類,這個原則在簡單工廠模式和工廠方法模式篇已經反覆講到了,這是面向接口編程的一個基本準則,很顯然,從抽象工廠模式的通常定義中能夠看出這也是抽象工廠模式的一個核心,而抽象工廠模式的另外一個核心是要解決一系列相關或相依賴對象(產品族)建立的問題。這也是這幾種工廠模式的細節區別所在的關鍵點所在,初學設計模式時每每由於沒有認識到這一點區別而對幾種工廠模式難以理解ide
咱們能夠簡單的這麼理解,抽象工廠模式不僅僅要解決對象的建立問題,還要涉及到建立的對象之間的相互依賴或者約束關係。工廠方法模式和簡單工廠模式解決了單個產品對象建立的問題,它們只關心單個產品對象的建立,而抽象工廠模式是關注的產品族(多個相互關聯對象)的建立,最終建立的產品族造成一個新的產品對象。spa
抽象工廠模式的結構圖以下:設計
AbstractFactory:抽象工廠類,定義建立某個產品所需相關對象的操做接口3d
ProductFactory1/ProductFactory2:具體的工廠類,實現抽象工廠定義的方法,負責某個產品所需全部對象建立操做接口的具體實現。code
AbstractProductA/AbstractProductB:定義某一類產品對象的接口
ProductA1/ProductA2/ProductB1/ProductB2:具體產品對象的實現
若是對上面的文字描述還不能有一個直觀的認識,咱們仍然從一個簡單的應用場景來講明抽象工廠模式的引入時機。
野外商店老闆爲了更好的服務衆英雄,特將店內隱身藥水進行了一次升級,分爲紅瓶裝(瓶口直徑2cm)、藍瓶裝(瓶口直徑5cm)2款,而且2種瓶子分別搭配圓形(2cm)和方形(5cm)兩種款式的瓶蓋。英雄們來到商店後,只須要將本身的的須要告訴商店老闆,老闆根據英雄的要求,去取瓶子和蓋子進行組裝便可。
在應用抽象工廠模式以前,咱們很簡單的使用簡單工廠模式實現這個需求。
定義瓶子接口及實現類
/// <summary> /// 定義瓶子接口 /// </summary> public interface IBottle { /// <summary> /// 展現本身的信息 /// </summary> void ShowInfo(); }
/// <summary> /// 紅色瓶子 /// </summary> public class RedBottle : IBottle { /// <summary> /// 展現本身的信息 /// </summary> public void ShowInfo() { Console.WriteLine("我是一個熱情火辣的紅色瓶子,個人瓶口直徑是2cm。"); } }
定義瓶蓋接口及實現類
/// <summary> /// 定義瓶蓋接口 /// </summary> public interface ICap { /// <summary> /// 展現本身的信息 /// </summary> void ShowInfo(); }
/// <summary> /// 圓形瓶蓋 /// </summary> public class RoundCap : ICap { /// <summary> /// 展現本身的信息 /// </summary> public void ShowInfo() { Console.WriteLine("我是一個圓形瓶蓋,個人直徑是2cm。"); } }
/// <summary> /// 方形瓶子 /// </summary> public class SquareCap : ICap { /// <summary> /// 展現本身的信息 /// </summary> public void ShowInfo() { Console.WriteLine("我是一個方形瓶蓋,個人直徑是5cm。"); } }
定義建立瓶子和瓶蓋的簡單工廠
/// <summary> /// 瓶子建立工廠方法 /// </summary> public class BottleFactory { /// <summary> /// 建立瓶子對象 /// </summary> /// <param name="color">瓶子顏色</param> /// <returns></returns> public static IBottle CreateBottle(string color) { if (color == "red") return new RedBottle(); if (color == "blue") return new BlueBottle(); return null; } }
/// <summary> /// 瓶蓋建立工廠方法 /// </summary> public class CapFactory { /// <summary> /// 建立瓶子對象 /// </summary> /// <param name="shape">瓶蓋形狀</param> /// <returns></returns> public static ICap CreateCap(string shape) { if (shape == "round") return new RoundCap(); if (shape == "square") return new SquareCap(); return null; } }
最終成品組裝類定義
/// <summary> /// 隱形藥水組裝者 /// </summary> public class ProductMaker { private IBottle _bottle; // 瓶子對象 private ICap _cap; // 瓶蓋對象 /// <summary> /// 建立最終藥水對象 /// </summary> /// <param name="bottleColor"></param> /// <param name="capShape"></param> public void MakeProduct(string bottleColor, string capShape) { _bottle = BottleFactory.CreateBottle(bottleColor); _cap = CapFactory.CreateCap(capShape); Console.WriteLine("準備英雄須要的瓶子和瓶蓋。"); _bottle.ShowInfo(); _cap.ShowInfo(); Console.WriteLine("開始往瓶子了灌入隱形藥水,而後封上瓶蓋。"); } }
客戶端調用
static void Main(string[] args) { ProductMaker pm = new ProductMaker(); pm.MakeProduct("red", "round"); // 提供給英雄紅瓶子圓蓋子的隱形藥水 Console.WriteLine(); pm.MakeProduct("blue", "square"); // 提供給英雄藍瓶子方蓋子的隱形藥水 Console.ReadLine(); }
這樣,咱們經過接口進行隔離,解決了不一樣瓶子,不一樣蓋子建立時,客戶端無需關心具體建立過程,只須要告訴工廠須要何種類型的對象便可。但同時會暴露一個很明顯的問題就是,咱們建立的瓶子和瓶蓋2個對象並非孤立存在的,2個對象之間是有明顯的相互關係的,那就是平口尺寸必須和瓶蓋尺寸保持一直,不然就會讓店老闆出現灌裝好藥水卻擰不上蓋子的尷尬。此時應該會對上面提到的抽象工廠的定義有進一步的理解,也在這種場景下,是咱們必需要引入抽象工廠模式的時候了。
0、提煉抽象工廠類
根據抽象工廠方法的結構圖,咱們首先定義個一個抽象工廠類,該抽象工廠定義瓶子和瓶蓋2個對象的建立接口。
/// <summary> /// 抽象工廠類 /// </summary> public abstract class AbstractFactory { /// <summary> /// 建立瓶子 /// </summary> /// <returns></returns> public abstract IBottle CreateBottle(); /// <summary> /// 建立瓶蓋 /// </summary> /// <returns></returns> public abstract ICap CreateCap(); }
一、抽象工廠的具體實現
分析產品的組合狀況,實際上只存在2種類型的最終產品,紅瓶子圓蓋子和藍瓶子方蓋子,咱們分別定義2個抽象工廠的具體實現類
/// <summary> /// 紅瓶子圓蓋子工廠類 /// </summary> public class RedBottleAndRoundCapFactory : AbstractFactory { /// <summary> /// 建立瓶子 /// </summary> /// <returns></returns> public override IBottle CreateBottle() { return BottleFactory.CreateBottle("red"); } /// <summary> /// 建立瓶蓋 /// </summary> /// <returns></returns> public override ICap CreateCap() { return CapFactory.CreateCap("round"); } }
/// <summary> /// 藍瓶子方蓋子工廠類 /// </summary> public class BlueBottleAndSquareCapFactory : AbstractFactory { /// <summary> /// 建立瓶子 /// </summary> /// <returns></returns> public override IBottle CreateBottle() { return BottleFactory.CreateBottle("blue"); } /// <summary> /// 建立瓶蓋 /// </summary> /// <returns></returns> public override ICap CreateCap() { return CapFactory.CreateCap("square"); } }
二、最終產品組裝類的修改實現
跟原來的實現相比較,最終產品組裝類不在從客戶端傳入瓶子、瓶蓋的參數經過對應的工廠方法建立,而是直接傳入已經定義好的瓶子瓶蓋組裝工廠類對象,可以作到瓶子瓶蓋必須配套建立。
/// <summary> /// 建立最終藥水對象 /// </summary> /// <param name="factory">抽象工廠具體對象</param> public void MakeProduct(AbstractFactory factory) { _bottle = factory.CreateBottle(); _cap = factory.CreateCap(); Console.WriteLine("準備英雄須要的瓶子和瓶蓋。"); _bottle.ShowInfo(); _cap.ShowInfo(); Console.WriteLine("開始往瓶子了灌入隱形藥水,而後封上瓶蓋。"); }
三、客戶端調用
ProductMaker pm = new ProductMaker(); AbstractFactory factory = new RedBottleAndRoundCapFactory(); // 提供給英雄紅瓶子圓蓋子的隱形藥水 pm.MakeProduct(factory); Console.WriteLine(); factory = new BlueBottleAndSquareCapFactory(); // 提供給英雄藍瓶子方蓋子的隱形藥水 pm.MakeProduct(factory); Console.ReadLine();
經過建立的多個對象之間的關聯關係闡述了抽象工廠模式與其餘工廠模式的區別以及使用時機。基於上面的示例,咱們能夠總結出抽象工廠模式的具備如下優勢:
0、分離接口和實現
客戶端使用抽象工廠方法來建立須要的對象,只須要傳入抽象方法的,無需關注內部具體實現邏輯,實現接口與具體實現的分離解耦。
一、易於產品族切換
一個具體抽象工廠的實現其實就是表明一個產品族,客戶端經過參數選用不一樣的工廠實現,就能夠在不一樣的產品建立中進行切換。
抽象工廠模式的缺點也顯而易見,那就是擴展新產品的過程會比較麻煩,好比一個產品族中包含的產品發生了變化,好比增長或減小部件,就須要修改抽象工廠,同時須要修改全部的抽象工廠實現類。