-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathFactoryPattern.md
353 lines (266 loc) · 9.32 KB
/
FactoryPattern.md
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
# 工厂模式
工厂模式根据抽象程度的不同分为三种:简单工厂模式(也叫静态工厂模式)、工厂方法模式、抽象工厂模式。
## 简单工厂模式
可以根据参数的不同返回不同类的实例。
简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
### Button 样例
```swift
enum Style {case mac, win}
protocol Button {}
class MacButton: Button {}
class WinButton: Button {}
class ButtonFactory {
func createButton(style: Style) -> Button {
switch style {
case .mac:
return MacButton()
default:
return WinButton()
}
}
}
var style: Style = .mac
var fac = ButtonFactory()
fac.createButton(style: style)
```
### Shape 样例
```swift
protocol Shape {
func draw()
}
class Rectangle : Shape {
func draw() {
print("Draw Rectangle")
}
}
class Square: Shape {
func draw() {
print("Draw Square")
}
}
class Circle: Square {
override func draw() {
print("Draw Circle")
}
}
class ShapeFactory {
func getShape(shapeType: String) -> Shape? {
if shapeType == "CIRCLE" {
return Circle()
} else if shapeType == "RECTANGLE" {
return Rectangle()
} else if shapeType == "SQUARE" {
return Square()
}
return nil
}
}
let facctory = ShapeFactory()
let circle = facctory.getShape(shapeType: "CIRCLE")
circle?.draw()
```
## 工厂方法模式
工厂方法模式是简单工厂的进一步深化,在工厂方法模式中,不再提供一个统一的工厂类来创建所有的对象,而是针对不同的对象提供不同的工厂。也就是说每个对象都有一个与之对应的工厂。
定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行
### Reader 样例
例如,有一个Reader类表示图片读取,另有它的三个子类 JPGReader, PNGReader和 GIFReader 分别代表 jpg、png 和 gif 读取。
```swift
protocol Reader {
func read()
}
class JPGReader : Reader {
func read() {
print("read jpg")
}
}
class PNGReader: Reader {
func read() {
print("read png")
}
}
class GIFReader: Reader {
func read() {
print("read gif")
}
}
protocol ReaderFactory {
func getReader() -> Reader
}
class JPGReaderFactory : ReaderFactory {
func getReader() -> Reader {
JPGReader()
}
}
class PNGReaderFactory: ReaderFactory {
func getReader() -> Reader {
PNGReader()
}
}
class GIFReaderFactory: ReaderFactory {
func getReader() -> Reader {
GIFReader()
}
}
var factory: ReaderFactory = GIFReaderFactory()
var reader: Reader = factory.getReader()
reader.read() // read gif
factory = PNGReaderFactory()
reader = factory.getReader()
reader.read() // read png
factory = JPGReaderFactory()
reader = factory.getReader()
reader.read() // read jpg
```
### Button 样例
例如,有一个Button类表示按钮,另有它的两个子类WinButton和MacButton分别代表Windows和Mac风格的按钮。
```swift
protocol Button {}
class MacButton: Button {}
class WinButton: Button {}
protocol ButtonFactory {
func createButton() -> Button
}
class WinButtonFactory : ButtonFactory {
func createButton() -> Button { WinButton() }
}
class MacButtonFactory: ButtonFactory {
func createButton() -> Button { MacButton() }
}
enum Style {case mac, win}
var style: Style = .mac
var fac: ButtonFactory
switch style {
case .mac:
fac = MacButtonFactory()
default:
fac = WinButtonFactory()
}
fac.createButton()
```
## 抽象工厂模式
为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。
### 汽车样例
假设我们有两种产品接口 BenzCar、AudiCar 和 BmwCar ,每一种产品都支持多种系列,比如 Sport 系列和 Business 系列。这样每个系列的产品分别是 BenzSportCar, BenzBusinessCar, BmwSportCar, BmwBusinessCar,AudiSportCar,AudiBusinessCar 。为了可以在运行时刻创建一个系列的产品族,我们可以为每个系列的产品族创建一个工厂 SupportDriver 和 BusinessDriver 。每个工厂都有三个方法 createBenzCar ,createBmwCar 和 createAudiCar 并返回对应的产品,可以将这三个方法抽象成一个接口 Driver 。这样在运行时刻我们可以选择创建需要的产品系列
```swift
class BenzCar {
var name: String
init(name: String) {
self.name = name
}
func drive() {}
}
class BenzSportCar : BenzCar {
override func drive() {
print("\(name) :: BenzSportCart")
}
}
class BenzBusinessCar : BenzCar {
override func drive() {
print("\(name) :: BenzBusinessCar")
}
}
class BmwCar {
var name: String
init(name: String) {
self.name = name
}
func drive() {}
}
class BmwSportCar : BmwCar {
override func drive() {
print("\(name) :: BmwCSportCart")
}
}
class BmwBusinessCar : BmwCar {
override func drive() {
print("\(name) :: BmwBusinessCar")
}
}
class AudiCar {
var name: String
init(name: String) {
self.name = name
}
func drive() {}
}
class AudiSportCar : AudiCar {
override func drive() {
print("\(name) :: AudiCSportCart")
}
}
class AudiBusinessCar : AudiCar {
override func drive() {
print("\(name) :: AudiBusinessCar")
}
}
protocol Driver {
func createBenzCar(car: String) -> BenzCar
func createBmwCar(car: String) -> BmwCar
func createAudiCar(car: String) -> AudiCar
}
class SupportDriver : Driver {
func createBenzCar(car: String) -> BenzCar {
BenzSportCar.init(name: car)
}
func createBmwCar(car: String) -> BmwCar {
BmwSportCar.init(name: car)
}
func createAudiCar(car: String) -> AudiCar {
AudiSportCar.init(name: car)
}
}
class BusinessDriver: Driver {
func createBenzCar(car: String) -> BenzCar {
BenzBusinessCar.init(name: car)
}
func createBmwCar(car: String) -> BmwCar {
BmwBusinessCar.init(name: car)
}
func createAudiCar(car: String) -> AudiCar {
AudiBusinessCar.init(name: car)
}
}
let driver = BusinessDriver()
let car = driver.createAudiCar(car: "BusinessDriver")
car.drive()
```
### GUI 样例
假设我们有两种产品接口 Button 和 Border ,每一种产品都支持多种系列,比如 Mac 系列和 Windows 系列。这样每个系列的产品分别是 MacButton, WinButton, MacBorder, WinBorder 。为了可以在运行时刻创建一个系列的产品族,我们可以为每个系列的产品族创建一个工厂 MacFactory 和 WinFactory 。每个工厂都有两个方法 CreateButton 和 CreateBorder 并返回对应的产品,可以将这两个方法抽象成一个接口 AbstractFactory 。这样在运行时刻我们可以选择创建需要的产品系列
```swift
protocol Button {}
class MacButton: Button {}
class WinButton: Button {}
protocol Border {}
class MacBorder: Border {}
class WinBorder: Border {}
protocol AbstractFactory {
func createButton() -> Button
func createBorder() -> Border
}
class MacFactory: AbstractFactory {
func createButton() -> Button { MacButton() }
func createBorder() -> Border { MacBorder() }
}
class WinFactory: AbstractFactory {
func createButton() -> Button { WinButton() }
func createBorder() -> Border { WinBorder() }
}
enum Style { case mac, win}
var fac: AbstractFactory
var style: Style = .mac
switch style {
case .mac:
fac = MacFactory()
default:
fac = WinFactory()
}
let button: Button = fac.createButton()
let border: Border = fac.createBorder()
```
## 三者对比
| |简单工厂| 工厂方法| 抽象工厂|
| -- | -- | -- | --|
|特点| 使用静态方法通过接受参数的不同来返回不同的实例| 针对每一种产品提供一个工厂类 | 针对产品族 |
| 扩展方式 | 在不修改代码的前提下无法扩展 | 在同一级别中可以任意扩展 | 应对产品族的概念,可以增加新的产品线,但无法增加新的产品 |
| 优点 | 在于工厂类中包含了必要的逻辑,更具客户需要的条件动态实例化相关的类,对客户端来说,去掉了与具体产品的依赖 | 创建对象的接口,让子类去决定具体的实例化的对象,把简单的内部逻辑判断移到了客户端代码。工厂方法克服了简单工厂违背开放-封闭原则的缺点,又保持了封装对象创建过程的优点。| 分离了具体的类,抽象工厂模式帮助你控制一个应用创建的对象的类,客户通过他们的抽象接口操纵实例,产品的类名也在具体工厂的实现中被分离,它们不出现在客户代码中。它使得易于交换产品系列。|
| 缺点 | 工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,当增加新的产品时,会违反开发-封闭原则 | 不易于维护,假如某个具体的产品类需要进行一定的修改,很可能需要修改对应的工厂类。当同时需要修改多个产品类的时候,对工厂类的修改会变得相当麻烦 | 抽象工厂模式在于难于应对“新对象”的需求变动,难以支持新种类产品,难以扩展抽象工厂以生产新种类产品 |