工廠模式-------簡單工廠模式,工廠方法模式、抽象工廠模式
簡單工廠模式、工廠方法模式、抽象工廠模式,都是屬于創建型設計模式,嚴格上來說,簡單工廠模式不屬于23設計模式之一,因為它違背了開閉原則,
這三種設計模式,名字都包含“工廠”二字,如果沒有認真地對它們的設計思想、代碼進行認真比較,還真的很難區分出究竟是哪一種模式,很多開發者很容易混淆,
接下來,我就將這三種設計模式放在一篇文章,用C#來實作它們并放在一起進行比較,
一、簡單工廠模式
想象一下,現在商場有很多賣不同口味的冰激凌攤位,每個攤位的位置都不盡相同,每個商家只賣一種口味,商家提供了制作冰激凌的所有原料,需要顧客自己去制作,這時,同伴三個人,你說你去買冰激凌,讓大家說說都想買什么口味的冰激凌,最后三個人剛好喜歡的口味都不同,分別是蘋果味、香蕉味、橘子味,大家委托你去買,你就跑到了A攤位,自己調制起了一根(一個?)蘋果味的冰激凌,然后,你又跑到幾十米外另一攤位去制作香蕉味冰激凌,最后又跑到另一攤位去制作橘子味的冰激凌,終于買好了三根冰激凌,拿回去后,發現自己那杯蘋果味的已經融化了…如果,你們一行有十幾個人,每個人需要的口味都不同呢?這樣是不是很麻煩?
商場管理人員意識到了這個問題,想了一個方法,他將所有的口味的冰激凌攤位,全部集中到了商場入口處來賣,并且,訂購了一臺賣冰激凌的機器,機器上有一排按鈕,每個按鈕代表一種口味的冰激凌,你想買哪一種口味就點擊哪個按鈕,機器內部就會自己去制作一根該口味的冰激凌,然后吐出該冰激凌給顧客,可以發現,顧客只需按一個按鈕,根本不需要像之前那樣自己去制作冰激凌,機器制作冰激凌的程序對于顧客來說也是透明的,這種模式,就是我們的 簡單工廠模式 ,而生產冰激凌的機器,就是我們所說的 工廠 ,

1. 首先定義一個冰激凌介面,里邊只有一個方法,就是顯示是哪種口味
/// <summary> /// 冰激凌介面 /// </summary> public interface IceCream { void Taste(); }
2.定義三個類,AppleIceCream、BananaIceCream、OrangeIceCream,并繼承上面的介面,實作其中的方法,顯示自己獨特的口味
/// <summary> /// 蘋果 /// </summary> public class AppleIceCream : IceCream { public void Taste() { Console.WriteLine("這是蘋果口味的冰激凌"); } } /// <summary> /// 香蕉 /// </summary> public class BananaIceCream : IceCream { public void Taste() { Console.WriteLine("這是香蕉口味的冰激凌"); } } /// <summary> /// 橘子 /// </summary> public class OrangeIceCream : IceCream { public void Taste() { Console.WriteLine("這是橘子口味的冰激凌"); } }
3.定義一個工廠類,用來制作不同口味的冰激凌
/// <summary> /// 工廠(制作冰淇淋的機器) /// </summary> public class IceCreamFactory { public static IceCream creamIceCream(string taste) { IceCream iceCream = null; // 這里我們通過switch來判斷,具體制作哪一種口味的冰激凌 switch (taste) { case "Apple": iceCream = new AppleIceCream(); break; case "Orange": iceCream = new OrangeIceCream(); break; case "Banana": iceCream = new BananaIceCream(); break; default: break; } return iceCream; } }
4.最后看一下客戶端的代碼
static void Main(string[] args) { IceCream appleIceCream = IceCreamFactory.creamIceCream("Apple"); appleIceCream.Taste();//這是蘋果口味的冰激凌
IceCream bananaIceCream = IceCreamFactory.creamIceCream("Banana"); bananaIceCream.Taste();//這是香蕉口味的冰激凌
IceCream orangeIceCream = IceCreamFactory.creamIceCream("Orange"); orangeIceCream.Taste();//這是橘子口味的冰激凌
Console.ReadKey(); }
運行結果如下:
可以看到,簡單工廠模式確實很“簡單”,一般,簡單工廠方法模式中,工廠類中有一個方法,通過switch中不同的值或者if else陳述句來創建不同的物件并回傳,通常這個方法是一個靜態方法,(順便一提:簡單工廠模式也被稱作“靜態工廠模式”)在客戶端直接呼叫工廠類的該方法就可以,整個冰激凌的生產(創建不同口味冰激凌的程序)被這個工廠類封裝了,客戶端不用去關注這些細節,
二、工廠方法模式
用了簡單方法模式后,顧客們方便多了,想要哪種口味的冰激凌就直接點一下按鈕即可直接購買,現在,該機器只能賣三種口味的冰激凌,并沒有滿足很多顧客的需求,管理員打算再添加一種草莓味的冰激凌來滿足更多顧客,問題來了,整個機器已經做成了,按鈕數目為3也已經固定了,如果想要再添加一種口味,那么就要打開機器內部,往里邊添加制作草莓味冰激凌的原料以及制作工藝,還要在機器外部再增加一個按鈕,這可麻煩了,畢竟整個機器的布局什么的都固定下來了,
其實,這正是簡單工廠模式的缺點,其違背了開閉原則,擴展性差,觀察簡單工廠模式的工廠類代碼,我們可以發現,其內部做了很多邏輯的處理,通過switch值的不同來創建不同的物件,現在,如果要新增草莓味的冰激凌,首先要新增StrawberryIceCream,并且,還要在switch里邊,新增一個case分支,來判斷是否生產StrawberryIceCream,所以不是很合理,
通過 工廠方法模式 ,我們就能解決這一問題,仔細研究,之所以會產生上面的問題,是因為我們只有一個“工廠”,無論何種口味的冰激凌生產,都交給這個工廠去處理導致的,那么,現在,我們可以,設計多個“工廠”,每種工廠只負責生產一種口味的冰激凌,回到商場來,還是在商場入場處,我們購置多臺生產冰激凌的機器,每臺機器只能生產一種口味的冰激凌,每臺機器有一個按鈕,點擊下去就會吐出該口味冰激凌,然后將這些機器一個挨著一個排列起來就行,現在,如果要添加一種新的口味,那么只要再購置一臺機器,然后挨著放進去即可,
接下來,看看具體的代碼實作:
1. 和簡單工廠模式一樣,先定義一個介面,再定義AppleIceCream、BananaIceCream和OrangeIceCream去實作這個介面(看上面1和2步驟)
2.定義工廠介面
/// <summary> /// 工廠模式介面 /// </summary> public interface IceCreamFactory { IceCream CreateIceCream(); }
3.再分別定義AppleIceCreamFactory、BananaIceCreamFactory、OrangeIceCreamFactory,繼承剛剛定義的工廠介面
/// <summary> /// 蘋果工廠 /// </summary> public class AppleIceCreamFactory : IceCreamFactory { public IceCream CreateIceCream() { return new AppleIceCream(); } } /// <summary> /// 香蕉工廠 /// </summary> public class BananaIceCreamFactory : IceCreamFactory { public IceCream CreateIceCream() { return new BananaIceCream(); } } /// <summary> /// 橘子工廠 /// </summary> public class OrangeIceCreamFactory : IceCreamFactory { public IceCream CreateIceCream() { return new OrangeIceCream(); } }
4.客戶端代碼
static void Main(string[] args) { //生產蘋果味冰激凌 IceCreamFactory appleFactory = new AppleIceCreamFactory(); IceCream appleIceCream = appleFactory.CreateIceCream(); appleIceCream.Taste(); //生產香蕉口味冰激凌 IceCreamFactory bananaFactory = new BananaIceCreamFactory(); IceCream bananaIceCream = bananaFactory.CreateIceCream(); bananaIceCream.Taste(); //生產橘子口味冰激凌 IceCream orangeIceCream = new OrangeIceCreamFactory().CreateIceCream(); orangeIceCream.Taste();
Console.ReadKey(); }
運行結果如下
三、抽象工廠模式
可以想象,不同人的需求是不同的,有的人吃冰激凌是當做飯后甜點,有的人直接把它當飯吃,因此,商場為了讓顧客有多種選擇,想要對每種口味冰激凌的量進行分類,分為大份和小份的,比如我們之前生產的是大份的冰激凌,那么要完成生產多種口味小份的冰激凌,能怎么做呢?當然,商場可以再購置蘋果味冰激凌(小份)、香蕉味冰激凌(小份)、橘子味冰激凌(小份)的機器,然后挨著放在之前幾臺旁邊,這種思路就是我們上邊的工廠方法模式,可是,這樣就需要添加多了一倍的機器數量,想象一下,如果商場在一開始規劃的時候就已經打算賣兩種分量多種口味的冰激凌,那能怎么做呢?
由于每種口味的冰激凌,材料和制作工藝都是相同的,所以,我們完全可以,每臺機器負責生產特定口味的冰激凌,并配備兩個按鈕,用來區分生產大份的或者是小份的,這樣是比較符合現實的,這就是我們接下來要說的 抽象工廠模式,
1. 由于要生產不同大小的冰激凌,所以,現在冰激凌的介面有兩個,分別是 BigIceCream 和 SmallIceCream
public interface BigIceCream { void Taste(); } public interface SmallIceCream { void Taste(); }
2.定義各個口味的冰激凌,繼承剛剛定義的介面,實作其方法
public class BigAppleIceCream : BigIceCream { public void Taste() { Console.WriteLine("這是蘋果味冰激凌(大份)"); } } public class SmallAppleIceCream : SmallIceCream { public void Taste() { Console.WriteLine("這是蘋果味冰激凌(小份)"); } }
//后邊還有四個類BigBananaIceCream、SmallBananaIceCream、BigOrangeIceCream、SmallOrangeIceCream
3.定義工廠介面,可以看到,這里有兩個方法,分別生產小份大的和大份的
/// <summary> /// 生產小份大的和大份的介面 /// </summary> public interface IceCreamFactory { BigIceCream CreateBigIceCream(); SmallIceCream CreateSmallIceCream(); }
4.定義三個工廠類繼承上邊的介面并實作其方法
public class AppleIceCreamFactory : IceCreamFactory { public BigIceCream CreateBigIceCream() { return new BigAppleIceCream(); } public SmallIceCream CreateSmallIceCream() { return new SmallAppleIceCream(); } }
//這里是蘋果味的大份和小份,香蕉和橘子按同樣的方法添加
5.客戶端代碼
/// <summary> /// 抽象工廠模式 /// </summary> /// <param name="args"></param> static void Main(string[] args) { //生產蘋果味冰激凌 IceCreamFactory appleIceCreamFactory = new AppleIceCreamFactory(); BigIceCream appleBigIceCream = appleIceCreamFactory.CreateBigIceCream(); SmallIceCream appleSmallIceCream = appleIceCreamFactory.CreateSmallIceCream(); appleBigIceCream.Taste(); appleSmallIceCream.Taste(); Console.ReadKey(); }
運行結果如下
可以看到,之所以叫抽象工廠,是因為和工廠方法相比,這里有多個抽象產品類存在(即大份的冰激凌和小份的冰激凌),每個抽象產品類可以派生出多個具體的產品,生產的是系列產品,其工廠介面相對于工廠方法模式而言,是有多個方法的,用來生產不同的抽象產品,
不過,我們也很容易看出,抽象工廠模式的弊端,比如現在,商場想要提供的是大、中、小三種系列產品,那么現在,需要改動的代碼就有點多了,首先需要創建一個介面,用來生產中份的冰激凌,然后還要實作具體的類,還需要修改工廠介面,并修改具體的工廠類,
四、總結
通過UML圖以及代碼不難對三種工廠模式進行一個區分,簡單工廠模式,工廠類是整個模式的關鍵所在,包含了必要的邏輯判斷,能夠外界給定的資訊, 決定究竟創建哪個具體類的物件,工廠方法模式 是對簡單工廠方法模式的一個抽象,抽離出了一個Factory類(或者介面),這個介面不負責具體產品的生產,而只是指定一些規范,具體的生產作業由其子類去完成,這個模式中,工廠類和產品類往往是一一對應的,完全解決了簡單工廠模式中違背“開閉原則”的問題,實作了可擴展;抽象工廠模式 的特點是存在多個抽象產品類,每個抽象產品類可以派生出多個具體產品類,工廠提供多種方法,去生產“系列”產品,
簡單工廠模式適用于工廠類需要創建的物件比較少的情況,客戶只需要傳入具體的引數,就可以忽略工廠的生產細節,去獲取想要的物件;
工廠方法模式,主要是針對單一產品結構的情景;
抽象工廠模式則是針對多級產品結構(系列產品)的一種工廠模式,
最后在說一下,每種模式都有自己的優點和弊端,沒有最好的模式,只有最適合的模式,只要符合實際開發需求就是最好的,
原文鏈接:https://blog.csdn.net/weixin_35985385/article/details/81430545
原文是用java實作的,我這里是用C#實作的
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/8589.html
標籤:設計模式
上一篇:設計模式:程式員跳不開的坑



