设计模式学习-工厂模式

工厂模式

工厂方法模式通过选取相关的实现类来满足调用组件的请求,调用组件无需了解这些实现。

何时使用

调用组件需要根据不同情况调用多个类的时候可以考虑使用工厂

下面是示例代码

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
///用基类实现更合适。协议感觉有点怪。特别是下面这个全局函数
func createRentalCar(by passengers:Int) -> RentalCar? {
var car:RentalCar?
switch passengers {
case 0...1:
car = Sports()
case 2...3:
car = Compact()
case 4...8:
car = SUV()
case 9...14:
car = Minivan()
default:
car = nil
}
return car
}
///RentalCar.swift
protocol RentalCar {
var name:String { get }
var passengers:Int { get }
var pricePerDay:Float { get }
}
class Compact: RentalCar {
var name: String = "VM Golf"
var passengers: Int = 3
var pricePerDay: Float = 20
}
class Sports: RentalCar {
var name: String = "Porsche Boxter"
var passengers: Int = 1
var pricePerDay: Float = 100
}
class SUV: RentalCar {
var name: String = "Cadillac Escalade"
var passengers: Int = 8
var pricePerDay: Float = 75
}
//CarSelector.swift
class CarSelector{
class func selectCar(by passengers:Int) -> String?{
let car = createRentalCar(by: passengers)
return car?.name
}
}
//main.swift
let passengers = [1,3,5]
for p in passengers{
print("\(p) passegers: \(CarSelector.selectCar(by: p) ?? "")")
}
class PriceCalculator {
class func calculatePrice(by passengers:Int,and totalDays:Int) -> Float?{
if let car = createRentalCar(by: passengers) {
return car.pricePerDay * Float(totalDays)
}
return nil
}
}

输出

1
2
3
4
5
Hello, World!
1 passegers: Porsche Boxter
3 passegers: VM Golf
5 passegers: Cadillac Escalade
Program ended with exit code: 0

抽象工厂

和简单工厂不一样的是,这个模式可以提供一组对象。

好处:可以在不修改调用组件的情况下,对其使用的类进行修改

什么时候使用:

当调用组件需要一组互相关联的对象,但这些对象又没有共同的父类和协议的时候。

下面是示例代码。创建一个命令行项目AbstractFactory

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
///FloorPlans.swift
enum EngineOption : String{
case front = "Front"
case mid = "Mid"
}
protocol Floorplan {
var seats:Int{ get }
var enginePosition:EngineOption { get }
}
class ShortFloorplan: Floorplan {
var seats: Int = 2
var enginePosition: EngineOption = .mid
}
class StandardFloorplan: Floorplan {
var seats: Int = 4
var enginePosition: EngineOption = .front
}
class LongFloorplan: Floorplan {
var seats: Int = 8
var enginePosition: EngineOption = .front
}
///Suspension.swift
enum SuspensionOption : String{
case standard = "Standard"
case sports = "Firm"
case soft = "Soft"
}
protocol Suspension {
var suspensionType:SuspensionOption { get }
}
class RoadSuspension: Suspension {
var suspensionType: SuspensionOption = .standard
}
class OffRoadSuspension: Suspension {
var suspensionType: SuspensionOption = .soft
}
class RaceSuspension: Suspension {
var suspensionType: SuspensionOption = .sports
}
///Drivetrains.swift
enum DriveOption : String{
case front = "Front"
case rear = "Rear"
case all = "4WD"
}
protocol Drivetrain {
var driveType:DriveOption { get }
}
class FrontWheelDrive: Drivetrain {
var driveType: DriveOption = .front
}
class RearWheelDrive: Drivetrain {
var driveType: DriveOption = .rear
}
class AllWheelDrive: Drivetrain {
var driveType: DriveOption = .all
}
///CarParts.swift
enum Cars : String {
case compact = "VM Golf"
case sports = "Porsche Boxter"
case suv = "Cadillac Escalade"
}
struct Car {
var carType:Cars
var floor:Floorplan
var suspension:Suspension
var drive:Drivetrain
func printDetail() {
print("Car type: \(carType.rawValue)")
print("Seats : \(floor.seats)")
print("Engine : \(floor.enginePosition.rawValue)")
print("Suspension : \(suspension.suspensionType.rawValue)")
print("Drive : \(drive.driveType.rawValue)")
}
}
///Abstract.swift
class CarFactory {
final class func getFactory(car:Cars) -> CarFactory {
var factory:CarFactory
switch car {
case .compact:
factory = CompactCarFactory()
case .sports:
factory = SportsCarFactory()
case .suv:
factory = SUVCarFactory()
}
return factory
}
func createFloorplan() -> Floorplan {
fatalError("no implemention")
}
func createSuspension() -> Suspension {
fatalError("no implemention")
}
func createDrivetrain() -> Drivetrain {
fatalError("no implemention")
}
}
///Concrete.swift
class CompactCarFactory : CarFactory {
override func createFloorplan() -> Floorplan {
return StandardFloorplan()
}
override func createSuspension() -> Suspension {
return RoadSuspension()
}
override func createDrivetrain() -> Drivetrain {
return FrontWheelDrive()
}
}
class SportsCarFactory: CarFactory {
override func createFloorplan() -> Floorplan {
return ShortFloorplan()
}
override func createSuspension() -> Suspension {
return RaceSuspension()
}
override func createDrivetrain() -> Drivetrain {
return RearWheelDrive()
}
}
class SUVCarFactory: CarFactory {
override func createFloorplan() -> Floorplan {
return LongFloorplan()
}
override func createSuspension() -> Suspension {
return OffRoadSuspension()
}
override func createDrivetrain() -> Drivetrain {
return AllWheelDrive()
}
}

工程代码下载地址https://github.com/RockyAo/DesignPatternerLearn