天天看點

2--抽象工廠模式(Abstract Factory)

抽象工廠模式(Abstract Factory) ——探索設計模式系列之三 Terrylee , 2005 年 12 月 12 日 概述 在軟體系統中,經常面臨着“一系列互相依賴的對象”的建立工作;同時由于需求的變化,往往存在着更多系列對象的建立工作。如何應對這種變化?如何繞過正常的對象的建立方法( new ),提供一種“封裝機制”來避免客戶程式和這種“多系列具體對象建立工作”的緊耦合?這就是我們要說的抽象工廠模式。 意圖 提供一個建立一系列相關或互相依賴對象的接口,而無需指定它們具體的類。 模型圖 邏輯模型:

2--抽象工廠模式(Abstract Factory)

實體模型:

2--抽象工廠模式(Abstract Factory)

生活中的例子 抽象工廠的目的是要提供一個建立一系列相關或互相依賴對象的接口,而不需要指定它們具體的類。這種模式可以汽車制造廠所使用的金屬沖壓裝置中找到。這種沖壓裝置可以制造汽車車身部件。同樣的機械用于沖壓不同的車型的右邊車門、左邊車門、右前擋泥闆、左前擋泥闆和引擎罩等等。通過使用轉輪來改變沖壓盤,這個機械産生的具體類可以在三分鐘内改變。

2--抽象工廠模式(Abstract Factory)

抽象工廠之新解 虛拟案例 中國企業需要一項簡單的财務計算:每月月底,财務人員要計算員工的工資。 員工的工資 = ( 基本工資 + 獎金 - 個人所得稅 ) 。這是一個放之四海皆準的運算法則。 為了簡化系統,我們假設員工基本工資總是 4000 美金。 中國企業獎金和個人所得稅的計算規則是 :          獎金 = 基本工資 (4000) * 10%          個人所得稅 = ( 基本工資 + 獎金 ) * 40% 我們現在要為此建構一個軟體系統(代号叫 Softo ),滿足中國企業的需求。 案例分析 獎金 (Bonus) 、個人所得稅 (Tax) 的計算是 Softo 系統的業務規則 (Service) 。 工資的計算 (Calculator) 則調用業務規則 (Service) 來計算員工的實際工資。 工資的計算作為業務規則的前端 ( 或者用戶端 Client) 将提供給最終使用該系統的使用者 ( 财務人員 ) 使用。 針對中國企業為系統模組化 根據上面的分析,為 Softo 系統模組化如下:

2--抽象工廠模式(Abstract Factory)

  則業務規則 Service 類的代碼如下: 用戶端的調用代碼: 運作程式,輸入的結果如下: Chinese Salary is : 2640 針對美國企業為系統模組化 為了拓展國際市場,我們要把該系統移植給美國公司使用。 美國企業的工資計算同樣是 : 員工的工資 = 基本工資 + 獎金 - 個人所得稅。 但是他們的獎金和個人所得稅的計算規則不同于中國企業 : 美國企業獎金和個人所得稅的計算規則是 :         獎金 = 基本工資 * 15 %         個人所得稅 = ( 基本工資 * 5% + 獎金 * 25%)   根據前面為中國企業模組化經驗,我們僅僅将 ChineseTax 、 ChineseBonus 修改為 AmericanTax 、 AmericanBonus 。 修改後的模型如下:

2--抽象工廠模式(Abstract Factory)

  則業務規則 Service 類的代碼如下:  1

2--抽象工廠模式(Abstract Factory)

using  System;

 2

2--抽象工廠模式(Abstract Factory)

 3

2--抽象工廠模式(Abstract Factory)

namespace  AmericanSalary

 4

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{

 5

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

    /// <summary>

 6

2--抽象工廠模式(Abstract Factory)

    /// 公用的常量

 7

2--抽象工廠模式(Abstract Factory)

    /// </summary>

 8

2--抽象工廠模式(Abstract Factory)

    public class Constant

 9

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{

10

2--抽象工廠模式(Abstract Factory)

        public static double BASE_SALARY = 4000;

11

2--抽象工廠模式(Abstract Factory)

    }

12

2--抽象工廠模式(Abstract Factory)

}

13

2--抽象工廠模式(Abstract Factory)

 1

2--抽象工廠模式(Abstract Factory)

using  System;

 2

2--抽象工廠模式(Abstract Factory)

 3

2--抽象工廠模式(Abstract Factory)

namespace  AmericanSalary

 4

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{

 5

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

    /// <summary>

 6

2--抽象工廠模式(Abstract Factory)

    /// 計算美國個人獎金

 7

2--抽象工廠模式(Abstract Factory)

    /// </summary>

 8

2--抽象工廠模式(Abstract Factory)

    public class AmericanBonus

 9

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{

10

2--抽象工廠模式(Abstract Factory)

        public double Calculate()

11

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{

12

2--抽象工廠模式(Abstract Factory)

            return Constant.BASE_SALARY * 0.1;

13

2--抽象工廠模式(Abstract Factory)

        }

14

2--抽象工廠模式(Abstract Factory)

    }

15

2--抽象工廠模式(Abstract Factory)

}

16

2--抽象工廠模式(Abstract Factory)

 1

2--抽象工廠模式(Abstract Factory)

using  System;

 2

2--抽象工廠模式(Abstract Factory)

 3

2--抽象工廠模式(Abstract Factory)

namespace  AmericanSalary

 4

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{    

 5

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

    /// <summary>

 6

2--抽象工廠模式(Abstract Factory)

    /// 計算美國個人所得稅

 7

2--抽象工廠模式(Abstract Factory)

    /// </summary>

 8

2--抽象工廠模式(Abstract Factory)

    public class AmericanTax

 9

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{

10

2--抽象工廠模式(Abstract Factory)

        public double Calculate()

11

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{

12

2--抽象工廠模式(Abstract Factory)

            return (Constant.BASE_SALARY + (Constant.BASE_SALARY * 0.1)) * 0.4;

13

2--抽象工廠模式(Abstract Factory)

        }

14

2--抽象工廠模式(Abstract Factory)

    }

15

2--抽象工廠模式(Abstract Factory)

}

16

2--抽象工廠模式(Abstract Factory)

用戶端的調用代碼: 運作程式,輸入的結果如下: American Salary is : 2640 整合成通用系統 讓我們回顧一下該系統的發展曆程: 最初,我們隻考慮将 Softo 系統運作于中國企業。但随着 MaxDO 公司業務向海外拓展, MaxDO 需要将該系統移植給美國使用。 移植時, MaxDO 不得不抛棄中國企業的業務規則類 ChineseTax 和 ChineseBonus , 然後為美國企業建立兩個業務規則類 : AmericanTax,AmericanBonus 。最後修改了業務規則調用 Calculator 類。 結果我們發現:每當 Softo 系統移植的時候,就抛棄原來的類。現在,如果中國聯想集團要購買該系統,我們不得不再次抛棄 AmericanTax,AmericanBonus ,修改回原來的業務規則。 一個可以立即想到的做法就是在系統中保留所有業務規則模型,即保留中國和美國企業工資運算規則。

2--抽象工廠模式(Abstract Factory)

  通過保留中國企業和美國企業的業務規則模型,如果該系統在美國企業和中國企業之間切換時,我們僅僅需要修改 Caculator 類即可。 讓移植工作更簡單 前面系統的整合問題在于:當系統在客戶在美國和中國企業間切換時仍然需要修改 Caculator 代碼。 一個維護性良好的系統應該遵循“開閉原則”。即:封閉對原來代碼的修改,開放對原來代碼的擴充(如類的繼承,接口的實作) 我們發現不論是中國企業還是美國企業,他們的業務運規則都采用同樣的計算接口。 于是很自然地想到建立兩個業務接口類 Tax , Bonus ,然後讓 AmericanTax 、 AmericanBonus 和 ChineseTax 、 ChineseBonus 分别實作這兩個接口, 據此修正後的模型如下:

2--抽象工廠模式(Abstract Factory)

  此時用戶端代碼如下:

為業務規則增加工廠方法  1

2--抽象工廠模式(Abstract Factory)

 2

2--抽象工廠模式(Abstract Factory)

using  System;

 3

2--抽象工廠模式(Abstract Factory)

 4

2--抽象工廠模式(Abstract Factory)

namespace  InterfaceSalary

 5

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{

 6

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

    /// <summary>

 7

2--抽象工廠模式(Abstract Factory)

    /// 用戶端程式調用

 8

2--抽象工廠模式(Abstract Factory)

    /// </summary>

 9

2--抽象工廠模式(Abstract Factory)

    public class Calculator 

10

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{

11

2--抽象工廠模式(Abstract Factory)

        public static void Main(string[] args) 

12

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{

13

2--抽象工廠模式(Abstract Factory)

            Bonus bonus = new ChineseBonus();

14

2--抽象工廠模式(Abstract Factory)

            double bonusValue  = bonus.Calculate();

15

2--抽象工廠模式(Abstract Factory)

16

2--抽象工廠模式(Abstract Factory)

            Tax tax = new ChineseTax();

17

2--抽象工廠模式(Abstract Factory)

            double taxValue = tax.Calculate();

18

2--抽象工廠模式(Abstract Factory)

19

2--抽象工廠模式(Abstract Factory)

            double salary = 4000 + bonusValue - taxValue; 

20

2--抽象工廠模式(Abstract Factory)

21

2--抽象工廠模式(Abstract Factory)

            Console.WriteLine("Chinaese Salary is:" + salary);

22

2--抽象工廠模式(Abstract Factory)

            Console.ReadLine();

23

2--抽象工廠模式(Abstract Factory)

        }

24

2--抽象工廠模式(Abstract Factory)

    }

25

2--抽象工廠模式(Abstract Factory)

}

26

2--抽象工廠模式(Abstract Factory)

然而,上面增加的接口幾乎沒有解決任何問題,因為當系統的客戶在美國和中國企業間切換時 Caculator 代碼仍然需要修改。 隻不過修改少了兩處,但是仍然需要修改ChineseBonus,ChineseTax部分。緻命的問題是:我們需要将這個移植工作轉包給一個叫 Hippo 的軟體公司。 由于版權問題,我們并未提供 Softo 系統的源碼給 Hippo 公司,是以 Hippo 公司根本無法修改 Calculator ,導緻實際上移植工作無法進行。 為此,我們考慮增加一個工具類 ( 命名為 Factory) ,代碼如下:  1

2--抽象工廠模式(Abstract Factory)

using  System;

 2

2--抽象工廠模式(Abstract Factory)

 3

2--抽象工廠模式(Abstract Factory)

namespace  FactorySalary

 4

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{

 5

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

    /// <summary>

 6

2--抽象工廠模式(Abstract Factory)

    /// Factory類

 7

2--抽象工廠模式(Abstract Factory)

    /// </summary>

 8

2--抽象工廠模式(Abstract Factory)

    public class Factory

 9

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{

10

2--抽象工廠模式(Abstract Factory)

        public Tax CreateTax()

11

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{

12

2--抽象工廠模式(Abstract Factory)

            return new ChineseTax();

13

2--抽象工廠模式(Abstract Factory)

        }

14

2--抽象工廠模式(Abstract Factory)

15

2--抽象工廠模式(Abstract Factory)

        public Bonus CreateBonus()

16

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{

17

2--抽象工廠模式(Abstract Factory)

            return new ChineseBonus();

18

2--抽象工廠模式(Abstract Factory)

        }

19

2--抽象工廠模式(Abstract Factory)

    }

20

2--抽象工廠模式(Abstract Factory)

}

21

2--抽象工廠模式(Abstract Factory)

修改後的用戶端代碼:  1

2--抽象工廠模式(Abstract Factory)

 2

2--抽象工廠模式(Abstract Factory)

using  System;

 3

2--抽象工廠模式(Abstract Factory)

 4

2--抽象工廠模式(Abstract Factory)

namespace  FactorySalary

 5

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{

 6

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

    /// <summary>

 7

2--抽象工廠模式(Abstract Factory)

    /// 用戶端程式調用

 8

2--抽象工廠模式(Abstract Factory)

    /// </summary>

 9

2--抽象工廠模式(Abstract Factory)

    public class Calculator 

10

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{

11

2--抽象工廠模式(Abstract Factory)

        public static void Main(string[] args) 

12

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{

13

2--抽象工廠模式(Abstract Factory)

            Bonus bonus = new Factory().CreateBonus();

14

2--抽象工廠模式(Abstract Factory)

            double bonusValue  = bonus.Calculate();

15

2--抽象工廠模式(Abstract Factory)

16

2--抽象工廠模式(Abstract Factory)

            Tax tax = new Factory().CreateTax();

17

2--抽象工廠模式(Abstract Factory)

            double taxValue = tax.Calculate();

18

2--抽象工廠模式(Abstract Factory)

19

2--抽象工廠模式(Abstract Factory)

            double salary = 4000 + bonusValue - taxValue; 

20

2--抽象工廠模式(Abstract Factory)

21

2--抽象工廠模式(Abstract Factory)

            Console.WriteLine("Chinaese Salary is:" + salary);

22

2--抽象工廠模式(Abstract Factory)

            Console.ReadLine();

23

2--抽象工廠模式(Abstract Factory)

        }

24

2--抽象工廠模式(Abstract Factory)

    }

25

2--抽象工廠模式(Abstract Factory)

}

26

2--抽象工廠模式(Abstract Factory)

不錯,我們解決了一個大問題,設想一下:當該系統從中國企業移植到美國企業時,我們現在需要做什麼? 答案是 : 對于 Caculator 類我們什麼也不用做。我們需要做的是修改 Factory 類,修改結果如下:  1

2--抽象工廠模式(Abstract Factory)

using  System;

 2

2--抽象工廠模式(Abstract Factory)

 3

2--抽象工廠模式(Abstract Factory)

namespace  FactorySalary

 4

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{

 5

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

    /// <summary>

 6

2--抽象工廠模式(Abstract Factory)

    /// Factory類

 7

2--抽象工廠模式(Abstract Factory)

    /// </summary>

 8

2--抽象工廠模式(Abstract Factory)

    public class Factory

 9

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{

10

2--抽象工廠模式(Abstract Factory)

        public Tax CreateTax()

11

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{

12

2--抽象工廠模式(Abstract Factory)

            return new AmericanTax();

13

2--抽象工廠模式(Abstract Factory)

        }

14

2--抽象工廠模式(Abstract Factory)

15

2--抽象工廠模式(Abstract Factory)

        public Bonus CreateBonus()

16

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{

17

2--抽象工廠模式(Abstract Factory)

            return new AmericanBonus();

18

2--抽象工廠模式(Abstract Factory)

        }

19

2--抽象工廠模式(Abstract Factory)

    }

20

2--抽象工廠模式(Abstract Factory)

}

21

2--抽象工廠模式(Abstract Factory)

為系統增加抽象工廠方法 很顯然,前面的解決方案帶來了一個副作用:就是系統不但增加了新的類 Factory ,而且當系統移植時,移植工作僅僅是轉移到 Factory 類上,工作量并沒有任何縮減,而且還是要修改系統的源碼。 從 Factory 類在系統移植時修改的内容我們可以看出 : 實際上它是專屬于美國企業或者中國企業的。名稱上應該叫 AmericanFactory,ChineseFactory 更合适 . 解決方案是增加一個抽象工廠類 AbstractFactory ,增加一個靜态方法,該方法根據一個配置檔案 (App.config 或者 Web.config) 一個項 ( 比如 factoryName) 動态地判斷應該執行個體化哪個工廠類,這樣,我們就把移植工作轉移到了對配置檔案的修改。修改後的模型和代碼:  

2--抽象工廠模式(Abstract Factory)

抽象工廠類的代碼如下:  1

2--抽象工廠模式(Abstract Factory)

using  System;

 2

2--抽象工廠模式(Abstract Factory)

using  System.Reflection;

 3

2--抽象工廠模式(Abstract Factory)

 4

2--抽象工廠模式(Abstract Factory)

namespace  AbstractFactory

 5

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{

 6

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

     /// <summary>

 7

2--抽象工廠模式(Abstract Factory)

     /// AbstractFactory類

 8

2--抽象工廠模式(Abstract Factory)

     /// </summary>

 9

2--抽象工廠模式(Abstract Factory)

     public abstract class AbstractFactory

10

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{

11

2--抽象工廠模式(Abstract Factory)

        public static AbstractFactory GetInstance()

12

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{

13

2--抽象工廠模式(Abstract Factory)

            string factoryName = Constant.STR_FACTORYNAME.ToString();

14

2--抽象工廠模式(Abstract Factory)

15

2--抽象工廠模式(Abstract Factory)

            AbstractFactory instance;

16

2--抽象工廠模式(Abstract Factory)

17

2--抽象工廠模式(Abstract Factory)

            if(factoryName == "ChineseFactory")

18

2--抽象工廠模式(Abstract Factory)

                instance = new ChineseFactory();

19

2--抽象工廠模式(Abstract Factory)

            else if(factoryName == "AmericanFactory")

20

2--抽象工廠模式(Abstract Factory)

                instance = new AmericanFactory();

21

2--抽象工廠模式(Abstract Factory)

            else

22

2--抽象工廠模式(Abstract Factory)

                instance = null;

23

2--抽象工廠模式(Abstract Factory)

24

2--抽象工廠模式(Abstract Factory)

            return instance;

25

2--抽象工廠模式(Abstract Factory)

        }

26

2--抽象工廠模式(Abstract Factory)

27

2--抽象工廠模式(Abstract Factory)

        public abstract Tax CreateTax();

28

2--抽象工廠模式(Abstract Factory)

29

2--抽象工廠模式(Abstract Factory)

        public abstract Bonus CreateBonus();

30

2--抽象工廠模式(Abstract Factory)

    }

31

2--抽象工廠模式(Abstract Factory)

} 配置檔案: 1

2--抽象工廠模式(Abstract Factory)

<? xml version="1.0" encoding="utf-8"  ?>

2

2--抽象工廠模式(Abstract Factory)

< configuration >

3

2--抽象工廠模式(Abstract Factory)

     < appSettings >

4

2--抽象工廠模式(Abstract Factory)

         < add  key ="factoryName"  value ="AmericanFactory" ></ add >

5

2--抽象工廠模式(Abstract Factory)

     </ appSettings >

6

2--抽象工廠模式(Abstract Factory)

</ configuration >

7

2--抽象工廠模式(Abstract Factory)

采用上面的解決方案,當系統在美國企業和中國企業之間切換時,我們需要做什麼移植工作? 答案是 : 我們僅僅需要修改配置檔案,将 factoryName 的值改為 American 。 修改配置檔案的工作很簡單,隻要寫一篇幅配置文檔說明書提供給移植該系統的團隊 ( 比如 Hippo 公司 ) 就可以友善地切換使該系統運作在美國或中國企業。 最後的修正(不是最終方案) 前面的解決方案幾乎很完美,但是還有一點瑕疵,瑕疵雖小,但可能是緻命的。 考慮一下,現在日本 NEC 公司決定購買該系統, NEC 公司的工資的運算規則遵守的是日本的法律。如果采用上面的系統構架,這個移植我們要做哪些工作呢 ? 1.      增加新的業務規則類 JapaneseTax,JapaneseBonus 分别實作 Tax 和 Bonus 接口。 2.      修改 AbstractFactory 的 getInstance 方法,增加 else if(factoryName.equals("Japanese")){.... 注意 : 系統中增加業務規則類不是模式所能解決的,無論采用什麼設計模式, JapaneseTax,JapaneseBonus 總是少不了的。(即增加了新系列産品) 我們真正不能接受的是:我們仍然修要修改系統中原來的類 (AbstractFactory) 。前面提到過該系統的移植工作,我們可能轉包給一個叫 Hippo 的軟體公司。 為了維護版權,未将該系統的源碼提供給 Hippo 公司,那麼 Hippo 公司根本無法修改 AbstractFactory ,是以系統移植其實無從談起,或者說系統移植總要開發人員親自參與。 解決方案是将抽象工廠類中的條件判斷語句,用 .NET 中發射機制代替,修改如下: Chinese , American , Japanese 等這樣的字眼了。  1

2--抽象工廠模式(Abstract Factory)

using  System;

 2

2--抽象工廠模式(Abstract Factory)

using  System.Reflection;

 3

2--抽象工廠模式(Abstract Factory)

 4

2--抽象工廠模式(Abstract Factory)

namespace  AbstractFactory

 5

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{

 6

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

    /// <summary>

 7

2--抽象工廠模式(Abstract Factory)

    /// AbstractFactory類

 8

2--抽象工廠模式(Abstract Factory)

    /// </summary>

 9

2--抽象工廠模式(Abstract Factory)

    public abstract class AbstractFactory

10

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{

11

2--抽象工廠模式(Abstract Factory)

        public static AbstractFactory GetInstance()

12

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{

13

2--抽象工廠模式(Abstract Factory)

            string factoryName = Constant.STR_FACTORYNAME.ToString();

14

2--抽象工廠模式(Abstract Factory)

15

2--抽象工廠模式(Abstract Factory)

            AbstractFactory instance;

16

2--抽象工廠模式(Abstract Factory)

17

2--抽象工廠模式(Abstract Factory)

            if(factoryName != "")

18

2--抽象工廠模式(Abstract Factory)

                instance = (AbstractFactory)Assembly.Load(factoryName).CreateInstance(factoryName);

19

2--抽象工廠模式(Abstract Factory)

            else

20

2--抽象工廠模式(Abstract Factory)

                instance = null;

21

2--抽象工廠模式(Abstract Factory)

22

2--抽象工廠模式(Abstract Factory)

            return instance;

23

2--抽象工廠模式(Abstract Factory)

        }

24

2--抽象工廠模式(Abstract Factory)

25

2--抽象工廠模式(Abstract Factory)

        public abstract Tax CreateTax();

26

2--抽象工廠模式(Abstract Factory)

27

2--抽象工廠模式(Abstract Factory)

        public abstract Bonus CreateBonus();

28

2--抽象工廠模式(Abstract Factory)

    }

29

2--抽象工廠模式(Abstract Factory)

}

30

2--抽象工廠模式(Abstract Factory)

這樣,在我們編寫的代碼中就不會出現 小結 最後那幅圖是最終版的系統模型圖。我們發現作為用戶端角色的 Calculator 僅僅依賴抽象類, 它不必去了解中國和美國企業具體的業務規則如何實作, Calculator 面對的僅僅是業務規則接口 Tax 和 Bonus 。 Softo 系統的實際開發的分工可能是一個團隊專門做業務規則,另一個團隊專門做前端的業務規則組裝。 抽象工廠模式有助于這樣的團隊的分工 : 兩個團隊通訊的約定是業務接口,由抽象工廠作為紐帶粘合業務規則和前段調用,大大降低了子產品間的耦合性,提高了團隊開發效率。 完完全全地了解抽象工廠模式的意義非常重大,可以說對它的了解是你對 OOP 了解上升到一個新的裡程碑的重要标志。 學會了用抽象工廠模式編寫架構類,你将了解 OOP 的精華 : 面向接口程式設計 . 。 應對“新對象” 抽象工廠模式主要在于應對“新系列”的需求變化。其缺點在于難于應付“新對象”的需求變動。如果在開發中出現了新對象,該如何去解決呢?這個問題并沒有一個好的答案,下面我們看一下李建忠老師的回答: “ GOF 《設計模式》中提出過一種解決方法,即給建立對象的操作增加參數,但這種做法并不能令人滿意。事實上,對于新系列加新對象,就我所知,目前還沒有完美的做法,隻有一些演化的思路,這種變化實在是太劇烈了,因為系統對于新的對象是完全陌生的。 ” 實作要點 l         抽象工廠将産品對象的建立延遲到它的具體工廠的子類。 l         如果沒有應對“多系列對象建立”的需求變化,則沒有必要使用抽象工廠模式,這時候使用簡單的靜态工廠完全可以。 l         系列對象指的是這些對象之間有互相依賴、或作用的關系,例如遊戲開發場景中的“道路”與“房屋”的依賴,“道路”與“道地”的依賴。 l         抽象工廠模式經常和工廠方法模式共同組合來應對“對象建立”的需求變化。 l         通常在運作時刻建立一個具體工廠類的執行個體,這一具體工廠的建立具有特定實作的産品對象,為建立不同的産品對象,客戶應使用不同的具體工廠。 l         把工廠作為單件,一個應用中一般每個産品系列隻需一個具體工廠的執行個體,是以,工廠通常最好實作為一個單件模式。 l         建立産品,抽象工廠僅聲明一個建立産品的接口,真正建立産品是由具體産品類建立的,最通常的一個辦法是為每一個産品定義一個工廠方法,一個具體的工廠将為每個産品重定義該工廠方法以指定産品,雖然這樣的實作很簡單,但它确要求每個産品系列都要有一個新的具體工廠子類,即使這些産品系列的差别很小。 優點 l         分離了具體的類。抽象工廠模式幫助你控制一個應用建立的對象的類,因為一個工廠封裝建立産品對象的責任和過程。它将客戶和類的實作分離,客戶通過他們的抽象接口操縱執行個體,産品的類名也在具體工廠的實作中被分離,它們不出現在客戶代碼中。 l         它使得易于交換産品系列。一個具體工廠類在一個應用中僅出現一次——即在它初始化的時候。這使得改變一個應用的具體工廠變得很容易。它隻需改變具體的工廠即可使用不同的産品配置,這是因為一個抽象工廠建立了一個完整的産品系列,是以整個産品系列會立刻改變。 l         它有利于産品的一緻性。當一個系列的産品對象被設計成一起工作時,一個應用一次隻能使用同一個系列中的對象,這一點很重要,而抽象工廠很容易實作這一點。 缺點 l         難以支援新種類的産品。難以擴充抽象工廠以生産新種類的産品。這是因為抽象工廠幾口确定了可以被建立的産品集合,支援新種類的産品就需要擴充該工廠接口,這将涉及抽象工廠類及其所有子類的改變。 适用性 在以下情況下應當考慮使用抽象工廠模式: l         一個系統不應當依賴于産品類執行個體如何被建立、組合和表達的細節,這對于所有形态的工廠模式都是重要的。 l         這個系統有多于一個的産品族,而系統隻消費其中某一産品族。 l         同屬于同一個産品族的産品是在一起使用的,這一限制必須在系統的設計中展現出來。 l         系統提供一個産品類的庫,所有的産品以同樣的接口出現,進而使用戶端不依賴于實作。 應用場景 l         支援多種觀感标準的使用者界面工具箱( Kit )。 l         遊戲開發中的多風格系列場景,比如道路,房屋,管道等。 l         …… 總結 總之,抽象工廠模式提供了一個建立一系列相關或互相依賴對象的接口,運用抽象工廠模式的關鍵點在于應對“多系列對象建立”的需求變化。一句話,學會了抽象工廠模式,你将了解 OOP 的精華:面向接口程式設計。    1

2--抽象工廠模式(Abstract Factory)

 2

2--抽象工廠模式(Abstract Factory)

using  System;

 3

2--抽象工廠模式(Abstract Factory)

 4

2--抽象工廠模式(Abstract Factory)

namespace  AmericanSalary

 5

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{

 6

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

    /// <summary>

 7

2--抽象工廠模式(Abstract Factory)

    /// 用戶端程式調用

 8

2--抽象工廠模式(Abstract Factory)

    /// </summary>

 9

2--抽象工廠模式(Abstract Factory)

    public class Calculator 

10

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{

11

2--抽象工廠模式(Abstract Factory)

        public static void Main(string[] args) 

12

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{

13

2--抽象工廠模式(Abstract Factory)

            AmericanBonus bonus = new AmericanBonus();

14

2--抽象工廠模式(Abstract Factory)

            double bonusValue  = bonus.Calculate();

15

2--抽象工廠模式(Abstract Factory)

16

2--抽象工廠模式(Abstract Factory)

            AmericanTax tax = new AmericanTax();

17

2--抽象工廠模式(Abstract Factory)

            double taxValue = tax.Calculate();

18

2--抽象工廠模式(Abstract Factory)

19

2--抽象工廠模式(Abstract Factory)

            double salary = 4000 + bonusValue - taxValue; 

20

2--抽象工廠模式(Abstract Factory)

21

2--抽象工廠模式(Abstract Factory)

            Console.WriteLine("American Salary is:" + salary);

22

2--抽象工廠模式(Abstract Factory)

            Console.ReadLine();

23

2--抽象工廠模式(Abstract Factory)

        }

24

2--抽象工廠模式(Abstract Factory)

    }

25

2--抽象工廠模式(Abstract Factory)

}

26

2--抽象工廠模式(Abstract Factory)

 1

2--抽象工廠模式(Abstract Factory)

using  System;

 2

2--抽象工廠模式(Abstract Factory)

 3

2--抽象工廠模式(Abstract Factory)

namespace  ChineseSalary

 4

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{    

 5

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

    /// <summary>

 6

2--抽象工廠模式(Abstract Factory)

    /// 計算中國個人所得稅

 7

2--抽象工廠模式(Abstract Factory)

    /// </summary>

 8

2--抽象工廠模式(Abstract Factory)

    public class ChineseTax

 9

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{

10

2--抽象工廠模式(Abstract Factory)

        public double Calculate()

11

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{

12

2--抽象工廠模式(Abstract Factory)

            return (Constant.BASE_SALARY + (Constant.BASE_SALARY * 0.1)) * 0.4;

13

2--抽象工廠模式(Abstract Factory)

        }

14

2--抽象工廠模式(Abstract Factory)

    }

15

2--抽象工廠模式(Abstract Factory)

}

16

2--抽象工廠模式(Abstract Factory)

 1

2--抽象工廠模式(Abstract Factory)

using  System;

 2

2--抽象工廠模式(Abstract Factory)

 3

2--抽象工廠模式(Abstract Factory)

namespace  ChineseSalary

 4

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{

 5

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

    /// <summary>

 6

2--抽象工廠模式(Abstract Factory)

    /// 公用的常量

 7

2--抽象工廠模式(Abstract Factory)

    /// </summary>

 8

2--抽象工廠模式(Abstract Factory)

    public class Constant

 9

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{

10

2--抽象工廠模式(Abstract Factory)

        public static double BASE_SALARY = 4000;

11

2--抽象工廠模式(Abstract Factory)

    }

12

2--抽象工廠模式(Abstract Factory)

}

 1

2--抽象工廠模式(Abstract Factory)

using  System;

 2

2--抽象工廠模式(Abstract Factory)

 3

2--抽象工廠模式(Abstract Factory)

namespace  ChineseSalary

 4

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{

 5

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

    /// <summary>

 6

2--抽象工廠模式(Abstract Factory)

    /// 計算中國個人獎金

 7

2--抽象工廠模式(Abstract Factory)

    /// </summary>

 8

2--抽象工廠模式(Abstract Factory)

    public class ChineseBonus

 9

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{

10

2--抽象工廠模式(Abstract Factory)

        public double Calculate()

11

2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)
2--抽象工廠模式(Abstract Factory)

{

12

2--抽象工廠模式(Abstract Factory)

            return Constant.BASE_SALARY * 0.1;

13

2--抽象工廠模式(Abstract Factory)

        }

14

2--抽象工廠模式(Abstract Factory)

    }

15

2--抽象工廠模式(Abstract Factory)

}

16

2--抽象工廠模式(Abstract Factory)

繼續閱讀