工廠設計模式: 顧名思義,該模式是用來生產對象的。在面向對象的設計模式中,萬物皆對象,若使用new來創建對象,就會對該對象產生強耦合,加入我們需要更換該對象,那麼使用該對象的對象都需要進行修改,這顯然違背了開閉原則(OCP)。如果我們使用工廠來產生對象,我們只需要與這個工廠打交道就可以了,無需關心具 ...
工廠設計模式:
顧名思義,該模式是用來生產對象的。在面向對象的設計模式中,萬物皆對象,若使用new來創建對象,就會對該對象產生強耦合,加入我們需要更換該對象,那麼使用該對象的對象都需要進行修改,這顯然違背了開閉原則(OCP)。如果我們使用工廠來產生對象,我們只需要與這個工廠打交道就可以了,無需關心具體的對象,達到解耦的目的。
接下來我們從實際的案例出發,從無工廠到有工廠的區別。
去披薩店訂購披薩,首先披薩的種類很多(CheesePizza、GreekPizza、DurianPizza{等),披薩的製作流程有prepare、bake、cut、box。
傳統模式:
1 internal class Program 2 { 3 private static void Main(string[] args) 4 { 5 new OrderPizza(); 6 } 7 } 8 9 internal class OrderPizza 10 { 11 public OrderPizza() 12 { 13 Pizza pizza = null; 14 string orderType = ""; 15 do 16 { 17 orderType = Console.ReadLine(); 18 if (orderType == "cheese") 19 { 20 pizza = new CheesePizza(); 21 pizza.setName("芝士披薩"); 22 } 23 else if (orderType == "greek") 24 { 25 pizza = new GreekPizza(); 26 pizza.setName("希臘披薩"); 27 } 28 else 29 { 30 Console.WriteLine("訂購失敗"); 31 break; 32 } 33 //開始製作 34 pizza.prepare(); 35 pizza.bake(); 36 pizza.cut(); 37 pizza.box(); 38 } while (true); 39 } 40 } 41 42 internal abstract class Pizza 43 { 44 private string name; 45 46 public abstract void prepare(); 47 48 public void bake() 49 { 50 Console.WriteLine($"{this.name} 烘培"); 51 } 52 53 public void cut() 54 { 55 Console.WriteLine($"{this.name} 修剪"); 56 } 57 58 public void box() 59 { 60 Console.WriteLine($"{this.name} 打包"); 61 } 62 63 public void setName(string name) 64 { 65 this.name = name; 66 } 67 } 68 69 internal class CheesePizza : Pizza 70 { 71 public override void prepare() 72 { 73 Console.WriteLine("芝士披薩準備中"); 74 } 75 } 76 77 internal class GreekPizza : Pizza 78 { 79 public override void prepare() 80 { 81 Console.WriteLine("希臘披薩準備中"); 82 } 83 }view code
傳統模式的優缺點:
1、比較好理解,易於操作
2、違反OCP原則,即對擴展開放,對修改關閉。
3、這裡只訂購了兩種pizza,若現在又新增了品種DurianPizza,這個時候就需要添加該類以及修改OrderPizza中的代碼。從上圖中可以看出,OrderPizza依賴抽象類及具體實現類的,那怎樣才能切斷OrderPizza與類之間的依賴關係呢。於是我們想到,可以定義一個工廠,訂購者不需要知道具體pizza的製作流程,只要直到我需要訂購什麼類型的pizza就行了。
簡單工廠模式:
1 internal class Program 2 { 3 private static void Main(string[] args) 4 { 5 new OrderPizza(); 6 } 7 } 8 9 internal class OrderPizza 10 { 11 public OrderPizza() 12 { 13 Pizza pizza = null; 14 string orderType = ""; 15 do 16 { 17 Console.Write("請輸入訂購類型:"); 18 orderType = Console.ReadLine(); 19 pizza = SimpleFactory.createPizza(orderType); 20 if (pizza == null) 21 { 22 Console.WriteLine("訂購失敗"); 23 break; 24 } 25 //開始製作 26 pizza.prepare(); 27 pizza.bake(); 28 pizza.cut(); 29 pizza.box(); 30 } while (true); 31 } 32 } 33 34 internal static class SimpleFactory 35 { 36 public static Pizza createPizza(string orderType) 37 { 38 Pizza pizza = null; 39 do 40 { 41 if (orderType == "cheese") 42 { 43 pizza = new CheesePizza(); 44 pizza.setName("芝士披薩"); 45 } 46 else if (orderType == "greek") 47 { 48 pizza = new GreekPizza(); 49 pizza.setName("希臘披薩"); 50 } 51 else if (orderType == "durian") 52 { 53 pizza = new DurianPizza(); 54 pizza.setName("榴蓮披薩"); 55 } 56 return pizza; 57 } while (true); 58 } 59 } 60 61 internal abstract class Pizza 62 { 63 private string name; 64 65 public abstract void prepare(); 66 67 public void bake() 68 { 69 Console.WriteLine($"{this.name} 烘培"); 70 } 71 72 public void cut() 73 { 74 Console.WriteLine($"{this.name} 修剪"); 75 } 76 77 public void box() 78 { 79 Console.WriteLine($"{this.name} 打包"); 80 } 81 82 public void setName(string name) 83 { 84 this.name = name; 85 } 86 } 87 88 internal class CheesePizza : Pizza 89 { 90 public override void prepare() 91 { 92 Console.WriteLine("芝士披薩準備中"); 93 } 94 } 95 96 internal class GreekPizza : Pizza 97 { 98 public override void prepare() 99 { 100 Console.WriteLine("希臘披薩準備中"); 101 } 102 } 103 104 internal class DurianPizza : Pizza 105 { 106 public override void prepare() 107 { 108 Console.WriteLine("榴蓮披薩準備中"); 109 } 110 }view code
簡單工廠模式優缺點:
1、由代碼可以看出,雖然簡單工廠模式一定程度上減少了因需求變更而導致的代碼更改,但是實際仍違背了OCP原則。
2、所以簡單工廠模式只適合產品對象相對較少,且產品固定的需求,對產品變化無常的需求來說顯然不適合。
工廠方法設計模式:
披薩項目需求變更,客戶點披薩時可以點不同口味的披薩。
1 internal class Program 2 { 3 private static void Main(string[] args) 4 { 5 new BJOrderPizza(); 6 } 7 } 8 9 internal abstract class OrderPizza 10 { 11 public OrderPizza() 12 { 13 Pizza pizza = null; 14 string orderType = ""; 15 do 16 { 17 Console.Write("請輸入訂購類型:"); 18 orderType = Console.ReadLine(); 19 pizza = createPizza(orderType); 20 if (pizza == null) 21 { 22 Console.WriteLine("訂購失敗"); 23 break; 24 } 25 //開始製作 26 pizza.prepare(); 27 pizza.bake(); 28 pizza.cut(); 29 pizza.box(); 30 } while (true); 31 } 32 33 public abstract Pizza createPizza(string orderType); 34 } 35 36 internal class BJOrderPizza : OrderPizza 37 { 38 public override Pizza createPizza(string orderType) 39 { 40 Pizza pizza = null; 41 if (orderType == "cheese") 42 { 43 pizza = new BJCheesePizza(); 44 } 45 else if (orderType == "greek") 46 { 47 pizza = new BJGreekPizza(); 48 } 49 return pizza; 50 } 51 } 52 53 internal class LDOrderPizza : OrderPizza 54 { 55 public override Pizza createPizza(string orderType) 56 { 57 Pizza pizza = null; 58 if (orderType == "cheese") 59 { 60 pizza = new LDCheesePizza(); 61 } 62 else if (orderType == "greek") 63 { 64 pizza = new LDGreekPizza(); 65 } 66 return pizza; 67 } 68 } 69 70 internal abstract class Pizza 71 { 72 private string name; 73 74 public abstract void prepare(); 75 76 public void bake() 77 { 78 Console.WriteLine($"{this.name} 烘培"); 79 } 80 81 public void cut() 82 { 83 Console.WriteLine($"{this.name} 修剪"); 84 } 85 86 public void box() 87 { 88 Console.WriteLine($"{this.name} 打包"); 89 } 90 91 public void setName(string name) 92 { 93 this.name = name; 94 } 95 } 96 97 internal class BJCheesePizza : Pizza 98 { 99 public override void prepare() 100 { 101 Console.WriteLine("北京的芝士披薩準備中"); 102 } 103 } 104 105 internal class BJGreekPizza : Pizza 106 { 107 public override void prepare() 108 { 109 Console.WriteLine("北京的希臘披薩準備中"); 110 } 111 } 112 113 internal class LDCheesePizza : Pizza 114 { 115 public override void prepare() 116 { 117 Console.WriteLine("倫敦的芝士披薩準備中"); 118 } 119 } 120 121 internal class LDGreekPizza : Pizza 122 { 123 public override void prepare() 124 { 125 Console.WriteLine("倫敦的希臘披薩準備中"); 126 } 127 }view code
工廠方法模式的優缺點:
1、讓父類的實現延遲到子類中去,減少判斷。
2、換湯不換藥,和簡單工廠模式類似,一般適用於產品對象相對較少,且產品固定的需求。
3、工廠方法一定程度上減輕了工廠的職責,將職責細化,避免工廠類無法正常運行而導致程式崩潰。
參考:https://www.jianshu.com/p/38493eb4ffbd