C#設計模式01-工廠方法模式(附原始碼)
工廠方法模式保證我們在增加新的具體產品時,不需要對現有的系統做任何修改!
工廠方法模式定義
定義一個用於建立物件的介面,但是由子類來決定例項化哪一個類。工廠方法模式將一個類的例項化延遲到子類。
為了避免工廠類職責過重,工廠方法模式裡面的工廠只負責生產一種具體產品!
汽車是我們生活中最常見的,考慮這樣一個情景。寶馬公司(BaoMaFactory)能生產寶馬汽車(BaoMa),大眾公司(DaZhongFactory)能生產大眾汽車(DaZhong)。寶馬公司,大眾公司這些工廠可以抽象出一個共同的父類,他們都是工廠(AbstractCarFactory)。他們所生產的的汽車也可以抽象出一個父類,即他們都是汽車(AbstractCar)。下面我們就用這個例子來說明一下工廠方法模式的UML圖:
從UML圖中大家應該看到了一點,如果這個時候我要新增一個豐田公司和豐田汽車,只需新增一個FengTianFactory類和FengTian類,不需要對以前的程式碼進行修改。
可以看得出來,父類AbstractCarFactory將不負責建立具體產品,而是將具體產品的建立工作交給子類(DaZhongFactory,BaoMaFactory)去做。也就是將產品的建立延遲到工廠子類去完成。
接下來說明工廠方法模式中的四種角色
(1)抽象工廠(AbstractCarFactory):宣告建立產品的介面。客戶端針對這個介面程式設計。
(2)實體工廠(BaoMaFactory,DaZhongFactory):它們是抽象工廠的子類,負責實現抽象工廠裡面建立產品的方法(CreateCar)。
(3)抽象產品(AbstractCar):它是所有具體產品的父類,宣告具體產品的公共方法,客戶端針對這個介面程式設計。
(4)具體產品(BaoMa,DaZhong):它是抽象產品的子類,負責實現抽象產品中宣告的方法(Run方法)。
最後分別把這四種角色的程式碼實現寫出來:
抽象工廠(AbstractCarFactory)的程式碼如下:
[csharp] view plain copy print ?
- namespace 工廠方法模式
- {
- interface AbstractCarFactory//汽車廠父類
- {
- AbstractCar CreateCar();//建立汽車(注意返回型別是AbstractCar)
- }
- }
- namespace 工廠方法模式
- {
- class BaoMaFactory:AbstractCarFactory//寶馬汽車廠
- {
- public AbstractCar CreateCar()
- {
- Console.WriteLine("建立了寶馬車!");
- return new BaoMa();
- }
- }
- }
- namespace 工廠方法模式
- {
- class DaZhongFactory:AbstractCarFactory//大眾汽車廠
- {
- public AbstractCar CreateCar()
- {
- Console.WriteLine("建立了大眾車!");
- return new DaZhong();
- }
- }
- }
[csharp] view plain copy print ?
- namespace 工廠方法模式
- {
- interface AbstractCar//抽象汽車
- {
- void Run();//汽車行駛方法
- }
- }
[csharp] view plain copy print ?
- namespace 工廠方法模式
- {
- class BaoMa:AbstractCar//寶馬汽車
- {
- public void Run()
- {
- Console.WriteLine("被建立的寶馬車跑起來啦!");
- }
- }
- }
- namespace 工廠方法模式
- {
- class DaZhong:AbstractCar//大眾汽車
- {
- public void Run()
- {
- Console.WriteLine("被建立的大眾車跑起來啦!");
- }
- }
- }
- namespace 工廠方法模式
- {
- class Program
- {
- static void Main(string[] args)
- {
- AbstractCar car;
- AbstractCarFactory carFactory = new BaoMaFactory();//這裡可以通過配置檔案+反射機制實現。
- car=carFactory.CreatCar();
- car.Run();
- Console.ReadLine();
- }
- }
- }
程式的最終執行結果如下:
在上面的客戶端程式碼中,我們直接new了一個BaoMaFactory工廠,如果要換成大眾汽車廠就必須修改客戶端程式碼。這違背了開閉原則。所以現在通過把工廠儲存在配置檔案中,在客戶端通過反射機制動態獲取工廠。這樣可以在不修改原始碼的前提下,自由更換工廠。
所以優化後的客戶端程式碼如下:
[csharp] view plain copy print ?- namespace 工廠方法模式
- {
- class Program
- {
- static void Main(string[] args)
- {
- AbstractCar car;
- //從配置檔案獲取具體工廠名稱(這裡是寶馬工廠)
- string factoryFactoryName = ConfigurationManager.AppSettings["factory"];
- //通過反射建立工廠類的例項
- AbstractCarFactory carFactory = Assembly.Load("工廠方法模式").CreateInstance(factoryFactoryName)
- as AbstractCarFactory ;
- car = carFactory.CreatCar();
- car.Run();
- Console.ReadLine();
- }
- }
- }
配置檔案的程式碼如下:
<appSettings>
<add key="factory" value="工廠方法模式.BaoMaFactory"/>
</appSettings>
但是由於每一種具體產品都有一個對應的具體工廠。所以新增具體產品類的時候會導致系統中類的個數成對增加,在一定程度上增加了系統的複雜度,因為有了更多的類需要編譯和執行。如果系統中產品類很多這會導致類氾濫,所以工廠方法在使用時,要根據具體情況來決定。
原始碼下載地址:http://pan.baidu.com/s/1kUgSGQj 密碼:573g
下一篇中講給大家講解抽象工廠模式。