1. 程式人生 > >用心理解設計模式——抽象工廠模式 (Abstract Factory Pattern)

用心理解設計模式——抽象工廠模式 (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