用心理解設計模式——抽象工廠模式 (Abstract Factory Pattern)
前置文章: 用心理解設計模式——設計模式的原則
設計模式相關程式碼已統一放至 我的 Github
一、定義
建立型模式之一。
Provide an interface for creating families of related or dependent objects without specifying their concrete classes.
(為建立一組相關或相互依賴的物件提供一個介面,而且無需指定它們的具體類)
二、結構解析
抽象工廠模式的一般結構有四種角色:抽象工廠、具體工廠、抽象產品、具體產品。
它的角色組成和 工廠方法模式 的角色組成是一致的。並且,它也為建立產品物件提供了一個介面(抽象工廠)。
不同的是,工廠方法模式中,提供了一個用於建立物件的方法(一個工廠與一個產品相對應);而抽象工廠模式的抽象工廠類中,提供了一組用於建立物件的方法(一個工廠與一個產品等級相對應,其中每個方法分別負責建立不同族屬的產品物件),派生出的不同具體工廠類來代表不同產品等級。
使用時,不需要指定具體產品類來new,而是,先選擇一個具體工廠(確定產品等級),再選擇一個工廠中的用於建立產品物件的方法(確定產品族屬)。(這樣就能決定出將要建立 哪級哪族 的具體產品)
因為裡式替換原則,這裡也不需要用具體產品類來接收產生的產品物件,用抽象產品類接收即可。
三、評價
抽象工廠模式針對性地解決了具有 兩重不同修飾 / 等級+族屬式 / 二維表格式 特徵的產品物件的建立問題。
等級對應具體工廠類,族屬對應抽象產品類。(等級和族屬在一定情況下可交換維度進行實現。
如:
具有兩重不同修飾,毛長度 和 不同動物
具有兩重不同修飾,男女 和 公斤級
四、實現
namespace AbstractFactory
{
#region 抽象層
//抽象產品類
public abstract class AbstractProduct { }
//抽象產品 X族
public abstract class AbstractProductX : AbstractProduct { }
//抽象產品 Y族
public abstract class AbstractProductY : AbstractProduct { }
//抽象工廠:定義兩個介面,生產X族產品,也生產Y族產品。
public abstract class AbstractCreator
{
public abstract AbstractProductX CreateProductX();
public abstract AbstractProductY CreateProductY();
}
#endregion
#region 具體層
//具體工廠, 生產A級X族,A級Y族產品
public class CretorA : AbstractCreator
{
public override AbstractProductX CreateProductX() { return new ProductAX(); }
public override AbstractProductY CreateProductY() { return new ProductAY(); }
}
//具體工廠, 生產B級X族,B級Y族產品
public class CretorB : AbstractCreator
{
public override AbstractProductX CreateProductX() { return new ProductBX(); }
public override AbstractProductY CreateProductY() { return new ProductBY(); }
}
//具體產品,A級X族
public class ProductAX : AbstractProductX { }
//具體產品,A級Y族
public class ProductAY : AbstractProductY { }
//具體產品,B級X族
public class ProductBX : AbstractProductX { }
//具體產品,B級Y族
public class ProductBY : AbstractProductY { }
#endregion
public class Client
{
//客戶類 只依賴抽象工廠和抽象產品類, 不依賴實際工廠和產品類
//
public void Main()
{
//建造不同等級的工廠
AbstractCreator cretorA = new CretorA();
AbstractCreator cretorB = new CretorB();
//在工廠類中建立抽象產品的具體子類的例項。
//通過A級工廠生產X族產品
AbstractProduct productAX = cretorA.CreateProductX();
//通過A級工廠生產Y族產品
AbstractProduct productAY = cretorA.CreateProductY();
//通過B級工廠生產X族產品
AbstractProduct productBX = cretorB.CreateProductX();
//通過B級工廠生產Y族產品
AbstractProduct productBY = cretorB.CreateProductY();
}
}
}
五、新增產品等級和族屬
繼續參照此圖, 因為 等級對應具體工廠類,族屬對應抽象產品類。
1.等級新增時,要新增一個具體工廠類(C級...),另外要新增一批同等級的具體產品類,覆蓋每個族屬(上圖一橫行)。
2.族屬新增時,要新增一個抽象產品類(Z族...),另外要新增一批同族屬的具體產品類,覆蓋每個等級(上圖一豎行)。
特別的: 新增族屬時,要修改抽象工廠類,以新增一個建立新族屬產品的抽象方法(抽象工廠承擔著定義“建立產品的介面方法”的職責),此時,所有的具體工廠類也要隨之修改(實現該抽象方法)。
可見,等級新增易,族屬新增難(違背開閉原則)
六、擴充套件維度的設想
如何從 兩重不同修飾 / 等級+族屬式 / 二維表格式 擴充套件為 三重不同修飾 / ?+ 等級+族屬式 / 三維表格式 ?
甚至更多維。
如: 在此基礎上增加毛的顏色。
TODO