1、前言
上一篇寫了設計模式原則有助於我們開發程序的時候能寫出高質量的代碼(牽一發而不動全身),這個系列還是做個筆記溫習一下各種設計模式,下面就看看簡單工廠模式、工廠模式、抽象工廠模式。
2、簡單工廠模式
其實我們可以這么理解簡單工廠模式,就是專門負責生產對象的一個類,作用就是創建具體產品的實例。我們平時創建創建一個對象的時候通常都是new出來的,此時這個類就依賴與這個對象,說白了就是耦合度過高啦。需求變化的時候我們不得不去修改此類的源碼。這時候就要用面向對象(OO)的思想去處理這個問題。把變化大的類封裝起來,實現就不去動它。下面看個栗子,就生產、制造不同的汽車分析簡單工廠模式的作用。
/// <summary> /// 車 抽象類 /// </summary> public abstract class Car { /// <summary> /// 制造車--抽象方法 /// </summary> public abstract void Make(); /// <summary> /// 賣車--抽象方法 /// </summary> public abstract void Sale(); } /// <summary> /// 奧迪車 /// </summary> public class ADCar : Car { public override void Make() { Console.WriteLine("制造了一輛奧迪車"); } public override void Sale() { Console.WriteLine("銷售了一輛奧迪車"); } } /// <summary> /// 奔馳車 /// </summary> public class BCCar : Car { public override void Make() { Console.WriteLine("制造了一輛奔馳車"); } public override void Sale() { Console.WriteLine("銷售了一輛奔馳車"); } }
看客戶端的調用
Car c = new ADCar(); c.Make(); c.Sale(); Console.WriteLine("\n"); Car b = new BCCar(); b.Make(); b.Sale();

我們可以看都是通過new一個ADCar 來創建一個實例, 想要奔馳的一樣的要new一個出來 我想要n個那不是炸鍋了。所以這里就創建一個車的簡單工廠類。讓這個工廠類來創建Car實例。這里的switch是C#的語法糖,感覺是不是有點香。
/// <summary> /// 車的工廠類 /// </summary> public class CarFactory { public static Car OpCar(string carName) { Car? car = null; var ret = carName switch { "AD" => car=new ADCar(), "BC" => car=new BCCar(), _ => car=new ADCar() }; return ret; } } //客戶端調用 Car cc = CarFactory.OpCar("AD"); cc.Make(); cc.Sale(); Car cc1 = CarFactory.OpCar("BC"); cc1.Make(); cc1.Sale();

這時候是不是就可以了,解決了客戶端太過於依賴具體對象的問題,別急如果我再來一個寶馬 就要還添加一個繼承Car的BMCar 還要在 CarFactory的OpCar里面再加一個判斷。按照開閉原則來說添加類沒有啥影響,但是修改了CarFactory里面OpCar的代碼就不符合開閉原則了。下面的工廠模式就專門解決這個問題。
3、工廠模式
在簡單工廠模式中系統難以擴展且違背了開閉原則,這樣使得簡單工廠的實現邏輯過於復雜。工廠模式就是把具體創建類的實例中放在子工廠類中,工廠類不再負責所有產品的創建工廠類只提供創建實例。還是看上面的栗子我們加一個抽象工廠類出來,讓不同的品牌去繼承
/// <summary> /// 車工廠類 /// </summary> public abstract class CarFactory1 { /// <summary> /// 抽象方法 /// </summary> public abstract Car OpCar(); } /// <summary> /// 奧迪工廠 /// </summary> public class ADCarFactory1 : CarFactory1 { public override Car OpCar() { return new ADCar();//在具體的工廠中實例化產品 } } /// <summary> /// 奔馳工廠 /// </summary> public class BCCarFactory1 : CarFactory1 { public override Car OpCar() { return new BCCar();//在具體的工廠中實例化產品 } } //客戶端調用 CarFactory1 cf = new ADCarFactory1(); Car car = cf.OpCar(); car.Make(); car.Sale(); CarFactory1 cf2 = new BCCarFactory1(); Car car2 = cf2.OpCar(); car2.Make(); car2.Sale();
效果跟上面一樣的,這里是不是就實現了新增一個寶馬的話不用修改Factory里面的代碼了只要在創建一個BMCarFactory1跟BMCar就可以了。我們要獲取一個產品的時候我們就獲取一個具體的工廠來實例它。 它是不是解決了簡單工廠的不足也符合了開閉原則。問題也來了如果我不單單要銷售車、賣車 搞大了我還要賣飛機賣火箭咋搞。這種不可能再去創建無數個工廠嘛。來看看抽象工廠模式。
4、抽象工廠模式
工廠模式它功能單一點只針對一個品牌,解決不了一系列的問題,賣火箭、賣飛機等等這些不同的品牌。如果我們在設計程序中顯然工廠模式已經滿足不了我們的需求了。抽象工廠模式就能很好的解決這個問題。這里我們還是新增一個抽象類,他提供制造、銷售汽車的同事也提供制造銷售飛機。實現方法只要實現自己品牌的的產品就可以了。
/// <summary> /// 產品抽象類 /// </summary> public abstract class PcFactory { /// <summary> /// 車 /// </summary> /// <returns></returns> public abstract Car OpCar(); /// <summary> /// 飛機 /// </summary> /// <returns></returns> public abstract Plan OpPlan(); } /// <summary> /// 奧迪pc工廠 /// </summary> public class ADPcFactory : PcFactory { public override Car OpCar() { return new ADCar(); } public override Plan OpPlan() { return new ADPlan(); } } /// <summary> /// 奔馳pc工廠 /// </summary> public class BCPcFactory : PcFactory { public override Car OpCar() { return new BCCar(); } public override Plan OpPlan() { return new BCPlan(); } } //客戶端調用 PcFactory pf = new ADPcFactory(); Car adc = pf.OpCar(); Plan adc2 = pf.OpPlan(); adc.Make(); adc.Sale(); adc2.Make(); adc2.Sale(); PcFactory pf2 = new BCPcFactory(); Car abc = pf2.OpCar(); Plan abc2 = pf2.OpPlan(); abc.Make(); abc.Sale(); abc2.Make(); abc2.Sale();

我們可以看出抽象工廠跟工廠的區別就在於它能生產多種產品(車、飛機)工廠只能是單一的產品(車)。抽象類只注重創建的多個產品,不會關心具體的實現是什么。實現又是不通的產品工廠實現的。這樣的話客戶端也從具體的產品中解耦出來。
5、總結
簡單工廠模式
優點:降低刻度段與具體產品的耦合度,實現new讓工廠類去完成,也提高了代碼的復用率。
缺點:違反了開閉原則系統擴展困難,而且工廠類集中了所有的業務邏輯一旦出問題整個系統都要受牽連。
工廠模式
優點:符合開閉原則新增功能不會區修改以前的代碼。
缺點:產品功能單一寫車的功能只能弄車,而不能加飛機、火箭的操作。
抽象工廠模式
優點:降低系統耦合度利於維護擴展,對於加系列產品符合開閉原則;
缺點:對於功能添加又不符合開閉原則了。看着是不是跟優點有沖突。這樣說吧我現在要加一個寶馬類不用修改業務邏輯添加一個BMCarFactory1跟BMCar就可以了。這是系列問題。如果我要加一個銷毀的方法(之前就定義了制作、銷售)那是不是還要在抽象類Car、Plan里面加一個抽象方法 繼承里面的通通都要實現它。所以程序設計之初沒有考慮到后面一個一個的改很麻煩。
一個系統要求不被所有客戶端依賴到具體的實現這是所有工廠模式的應用的前提,這就要具體問題具體分析了。不可能說我要打印一個Holl Word還來搞設計模式嘛,高射炮打蚊子沒有必要。各種模式都有好有壞,相對論就是這么說的,你得到一些的時候必然會失去一些,快樂要有悲傷作伴,雨過自然天晴嗎。加了設計模式以后代碼量肯定要上去的帶給我們方便的同時也會增加風險。以前不解為啥要創建那么多項目,文件夾,現在想想就那么回事了。
PS:流年似水,歲月如歌,承受委屈是一種胸懷,接受誤解是一種心懷,這個世界上失去什么東西都不可怕,惟一可怕的是失去你的心,失去你的勇氣,只要你堅韌不拔地奮斗,只要你眼睛看向未來,生命就永遠屬於你,生命的輝煌也一定永遠屬於你。
