工厂设计模式:
顾名思义,该模式是用来生产对象的。在面向对象的设计模式中,万物皆对象,若使用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
原文地址:https://www.cnblogs.com/az4215/p/11516734.html