设计模式-创建型-工厂模式
工厂设计模式:
顾名思义,该模式是用来生产对象的。在面向对象的设计模式中,万物皆对象,若使用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、工厂方法一定程度上减轻了工厂的职责,将职责细化,避免工厂类无法正常运行而导致程序崩溃。
