- 简单工厂模式概述
- 定义:定义一个工厂类,他可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类
- 在简单工厂模式中用于被创建实例的方法通常为静态(static)方法,因此简单工厂模式又被成为静态工厂方法(Static Factory Method)
- 需要什么,只需要传入一个正确的参数,就可以获取所需要的对象,而无需知道其实现过程
- 例如,我开一家披萨店,当客户需要某种披萨并且我这家店里也能做的时候,我就会为其提供所需要的披萨(当然是要钱的哈哈),如果其所需的我这没有,则是另外的情况,后面会谈。这时候,我这家 披萨店就可以看做工厂(Factory),而生产出来的披萨被成为产品(Product),披萨的名称则被称为参数,工厂可以根据参数的不同返回不同的产品,这就是简单工厂模式
- 简单工厂模式的结构与实现
- 结构:
- Factory(工厂):核心部分,负责实现创建所有产品的内部逻辑,工厂类可以被外界直接调用,创建所需对象
- Product(抽象类产品):工厂类所创建的所有对象的父类,封装了产品对象的公共方法,所有的具体产品为其子类对象
- ConcreteProduct(具体产品):简单工厂模式的创建目标,所有被创建的对象都是某个具体类的实例。它要实现抽象产品中声明的抽象方法(有关抽象类)
- 实现
1 abstract class Product
2 {
3 public void MethName()
4 {
5 //公共方法的实现
6 }
7 public abstract void MethodDiff();
8 //声明抽象业务方法
9 }
10 class ConcreteProductA : Product
11 {
12 public override void MethodDiff()
13 {
14 //业务方法的实现
15 }
16 }
17
18 class Factory
19 {
20 public static Product GetProduct(string arg)
21 {
22 Product product = null;
23 if(arg.Equals("A")
24 {
25 product = new ConcreteProductA();
26 //init
27 }
28 else if(arg.Equals("B"))
29 {
30 product = new ConcreteProductB();
31 //init
32 }
33 else
34 {
35 ....//其他情况
36 }
37 return product;
38 }
39 }
40
41 class Program
42 {
43 static void Main(string[] args)
44 {
45 Product product;
46 product = Factory.GetProduct("A");//工厂类创建对象
47 Product.MethName();
48 product.MethodDiff();
49 }
50 }
- 简单工厂模式的简化
- 为了简化简单工厂模式,将抽象产品类和工厂类合并,将静态工厂方法移到抽象产品类中
- 客户端可以调用产品父类的静态工厂方法,根据不同的参数创建不同类型的产品子类对象。
- 简单工厂模式的优缺点和适用环境
- 简单工厂模式的优点
(1)工厂类包含必要的逻辑判断,可以决定在什么时候创建哪一个产品的实例。客户端可以免除直接创建产品对象的职责
(2)客户端无需知道所创建具体产品的类名,只需知道参数即可
(3)也可以引入配置文件,在不修改客户端代码的情况下更换和添加新的具体产品类。(这也是我在开始的披萨店里遇到没有的披萨的解决情况)
- 简单工厂模式的缺点
(1)工厂类集中了所有产品的创建逻辑,职责过重,一旦异常,整个系统将受影响
(2)使用简单工厂模式会增加系统中类的个数(引入新的工厂类),增加系统的复杂度和理解难度
(3)系统扩展困难,一旦增加新产品不得不修改工厂逻辑,在产品类型较多时,可能造成逻辑过于复杂
(4)简单工厂模式使用了static工厂方法,造成工厂角色无法形成基于继承的等级结构。
- 简单工厂模式的适用环境
(1)工厂类负责创建对的对象比较少,因为不会造成工厂方法中的业务逻辑过于复杂
(2)客户端只知道传入工厂类的参数,对如何创建对象不关心
- 简单案例
- 题目: 使用简单工厂模式设计一个可以创建不同几何图形(Shape),如Circle,Rectangle,Triangle等绘图工具类,每个几何图形均具有绘制Draw()和擦除Erase()两个方法
要求在绘制不支持的几何图形时,抛出一个UnsuppShapeException异常,绘制类图并使用C#语言实现。 - UML:
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 /*使用简单工厂模式设计一个可以创建不同几何图形(Shape),如Circle,Rectangle,Triangle等绘图工具类,每个几何图形均具有绘制Draw()和擦除Erase()两个方法
6 * 要求在绘制不支持的几何图形时,抛出一个UnsuppShapeException异常,绘制类图并使用C#语言实现。
7 */
8
9 namespace SimpleShapeFactory
10 {
11 public interface InShape//图形接口 抽象产品类
12 {
13 void Draw();
14 void Erase();
15 }
16
17 public class Circle : InShape//圆形类,具体产品类
18 {
19 private static int count; //生成图形计数
20 string radious;
21 public Circle()//构造
22 {
23 Console.WriteLine("Create Circle");
24 Console.WriteLine("Input the radious of Circle:");
25 radious = Console.ReadLine();
26 }
27 public void Draw()//实现接口方法
28 {
29 int Radious = int.Parse(radious);
30 Console.WriteLine("Display circle " + (++count) +" information:");
31 Console.WriteLine("Circle "+ count+ " circumference:" + 2 * Radious * 3.14159);
32 Console.WriteLine("Circle "+ count+" area:" + 3.14159 * Radious * Radious);
33 }
34 public void Erase()//实现接口方法
35 {
36 while (true)
37 {
38 Console.WriteLine("Erase current shape(y/n)?");
39 string choose;
40 choose = Console.ReadLine();
41 if (choose.Equals("y") || choose.Equals("Y"))
42 {
43 Console.WriteLine("Erase Circle "+count +" successfully!");
44 count--;
45 break;
46 }
47 else if (choose.Equals("n") || choose.Equals("N"))
48 {
49 Console.WriteLine("Circle "+ count+" successfully saved!");
50 break;
51 }
52 else
53 {
54 Console.WriteLine("Input error, re-enter!");
55 }
56 }
57 }
58 }
59
60 class Rectangle : InShape//矩形类,具体产品类
61 {
62 private static int count = 0;//生成图形计数
63 string length;
64 string wideth;
65 public Rectangle()//构造
66 {
67 Console.WriteLine("Create Rectangle");
68 Console.WriteLine("Input the length and wideth of Rectangle:");
69 length = Console.ReadLine();
70 wideth = Console.ReadLine();
71 }
72 public void Draw()//实现接口方法
73 {
74 int Length = int.Parse(length);
75 int Wideth = int.Parse(wideth);
76 Console.WriteLine("Display rectangle " + (++count) + " information:");
77 Console.WriteLine("Rectangle "+ count + "circumference:" + 2 * Length * Wideth);
78 Console.WriteLine("Rectangle "+ count + "area:" + Length * Wideth);
79
80 }
81 public void Erase()//实现接口方法
82 {
83 while (true)
84 {
85 Console.WriteLine("Erase current shape(y/n)?");
86 string choose;
87 choose = Console.ReadLine();
88 if (choose.Equals("y") || choose.Equals("Y"))
89 {
90 Console.WriteLine("Erase rectangle "+count+ "successfully!");
91 --count;
92 break;
93 }
94 else if (choose.Equals("n") || choose.Equals("N"))
95 {
96 Console.WriteLine("Rectangle "+ count+" successfully saved!");
97 break;
98 }
99 else
100 {
101 Console.WriteLine("Input error, re-enter!");
102 }
103 }
104 }
105 }
106
107 class Triangle : InShape//三角形类,具体产品类
108 {
109 private static int count = 0;//生成图形计数
110 string lengtha;
111 string lengthb;
112 string lengthc;
113 public Triangle()//构造
114 {
115 Console.WriteLine("Create Triangle");
116 Console.WriteLine("Input the lengtha ,lengthb and lengthc of Triangle:");
117 lengtha = Console.ReadLine();
118 lengthb = Console.ReadLine();
119 lengthc = Console.ReadLine();
120
121 }
122 public void Draw()//实现接口方法
123 {
124 int Lengtha = int.Parse(lengtha);
125 int Lengthb = int.Parse(lengthb);
126 int Lengthc = int.Parse(lengthc);
127 if ((Lengtha + Lengthb > Lengthc) && (Lengtha + Lengthc > Lengthb) && (Lengthb + Lengthc > Lengtha))
128 {
129 double S = (Lengtha + Lengthb + Lengthc) * 0.5;
130 double area = Math.Sqrt(S * (S - Lengtha) * (S - Lengthb) * (S - Lengthc));
131 Console.WriteLine("Display triangle "+ (++count)+" information:");
132 Console.WriteLine("Triangle " + count +" circumference:" + (Lengtha + Lengthb + Lengthc));
133 Console.WriteLine("Triangle "+ count +" area:" + area);
134 Erase();
135 }
136 else
137 {
138 Console.WriteLine("Create triangle failed!");
139 }
140 }
141 public void Erase()//实现接口方法
142 {
143 while (true)
144 {
145 Console.WriteLine("Erase shape(y/n)?");
146 string choose;
147 choose = Console.ReadLine();
148 if (choose.Equals("y") || choose.Equals("Y"))
149 {
150 Console.WriteLine("Erase tirangle " +count +" successfully!");
151 --count;
152 break;
153 }
154 else if (choose.Equals("n") || choose.Equals("N"))
155 {
156 Console.WriteLine("Triangle "+ count +" successfully saved!");
157 break;
158 }
159 else
160 {
161 Console.WriteLine("Input error, re-enter!");
162 }
163 }
164 }
165 }
166
167 class ShapeFactory//图形工厂类,充当工厂类
168 {
169 public static InShape Getshape(string type)//静态工厂方法
170 {
171 InShape shape;
172 shape = null;
173 if (type.Equals("Circle"))
174 {
175 shape = new Circle();
176 Console.WriteLine("Init set Circle");
177 shape.Draw();
178 shape.Erase();
179 }
180 else if(type.Equals("Rectangle"))
181 {
182 shape = new Rectangle();
183 Console.WriteLine("Init set Rectangle");
184 shape.Draw();
185 shape.Erase();
186 }
187 else if (type.Equals("Triangle"))
188 {
189 shape = new Triangle();
190 Console.WriteLine("Init set Triangle");
191 shape.Draw();
192
193 }
194 else//异常 这里我应该声明调用异常处理类的,那样会更好些
195 {
196 Console.WriteLine("UnsupportShapeException!");
197 Console.WriteLine("Emotional reminders :Pay 1 million$ to Alipay:132****6151 can create every shape you want!!! ");
198 }
199 return shape;
200 }
201 }
202
203 class Program//客户端测试类
204 {
205 static void Main(string[] args)
206 {
207 while (true)
208 {
209 InShape shape;
210 Console.WriteLine("Please input the shape you want to create");
211 string str = Console.ReadLine();
212 shape = ShapeFactory.Getshape(str);//通过静态工厂方法创建产品
213 Console.ReadLine();
214 }
215 }
216 }
217 }
- 运行结果:
- 自我感觉写的一般般,如有不对的地方,欢迎指正。