Introduction to the Factory Pattern and its Implementation in C++.
工厂模式的介绍及其C++实现。包含简单工厂模式、工厂方法模式、抽象工厂模式。
军工厂可以生产各种型号的飞机,比如J-20,Y-20,H-20。目前的态势需要哪种主力机型,军工厂就生产哪个机型。
工厂类AircraftFactory:定义一个用于创建指定的具体实例的接口CreateAircraft()
抽象产品类Aircraft:作为所有具体飞机的父类,抽象类。
具体产品类J20\Y20\H20:工厂类创建的就是这些类的实例。
枚举出所有飞机的种类
1
2
3
4
5
|
enum AIRCRAFT_TYPE {
J_20,
H_20,
Y_20
};
|
通过if或者switch判断客户传入的参数来生成对应的产品
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
class AircraftFactory {
public:
Aircraft* create(AIRCRAFT_TYPE type) {
switch (type) {
case AIRCRAFT_TYPE::J_20:
return new J20();
case AIRCRAFT_TYPE::H_20:
return new H20();
case AIRCRAFT_TYPE::Y_20:
return new Y20();
default:
return NULL;
}
}
};
|
就是一个父类抽象类,父类指针可以指向所有子类对象,返回值什么的用父类指针,调用的时候由于多态调用具体的子类的行为
1
2
3
4
5
|
class Aircraft {
public:
virtual ~Aircraft() = 0; // 基类的析构函数要为virtual
virtual void show() = 0; // 子类进行具体实现
};
|
继承自抽象产品类,定义每个具体产品的行为
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
class J20 : public Aircraft {
public:
void show() {
std::cout << "J20" << std::endl;
}
~J20() {}
};
class Y20 : public Aircraft {
public:
void show() {
std::cout << "Y20" << std::endl;
}
~Y20() {}
};
class H20 : public Aircraft {
public:
void show() {
std::cout << "H20" << std::endl;
}
~H20() {}
};
|
首先实例化出实际工厂,然后调用工厂提供的接口进行实例化你想要的具体的产品:
1
2
3
4
5
6
|
int main() {
AircraftFactory factory;
Aircraft* myJ20 = factory.create(J_20);
myJ20->show();
return 0;
}
|
虚析构/纯虚析构都具有函数体,这与普通纯虚函数有所不同。【即需要在析构函数中编写函数体】
1
2
3
4
5
6
|
class Aircraft {
public:
virtual ~Aircraft() = 0; // 基类的析构函数要为virtual
virtual void show() = 0; // 子类进行具体实现
};
Aircraft::~Aircraft() {} // 虚/纯虚析构的函数体需要显式定义
|
注意到我们在main中初始化出来的工厂factory给我们创建对象的时候是new出来的,所以在使用结束之后需要delete对象
1
2
3
|
Aircraft* myJ20 = factory.create(J_20);
myJ20->show();
delete myJ20; // 使用完毕之后释放对象
|
J20
- 将对象创建的逻辑封装在一个工厂类中,客户端不需要了解具体的类名,客户端不用自己实例化类
- 简化了对象创建的过程
简单工厂模式并没有被收录到23种设计模式中,严格来说简单工厂并不是一个标准的设计模式
- 简单性:所有具体产品的创建逻辑都在一个工厂类中,导致了工厂类会复杂且庞大
- 违反开闭原则:开闭原则指对扩展开放,对修改关闭,
- 当需要添加新功能时,应该通过增加新的代码(如新的类、方法)来实现,而不是修改现有的代码。
- 在已有功能稳定的前提下,避免对现有代码进行修改,这样可以减少对系统中其他部分的影响。
即你可以加代码,但你别改我原来的代码。而对于简单工厂来说,每次要加一个新产品,你就得修改工厂类里的switch或者if语句,以支持新产品的初始化,修改了原来稳定的代码,每次修改都会影响到所有产品。
现在态势很紧急,我三种先进战机都要大量进行生产,则要针对不同型号的战机开设自己的独立产品线,每个产品线只生产这个类型的战机。
抽象工厂类AircraftFactory:工厂方法模式的核心类,是抽象类、接口类,所有具体工程的父类。提供具体创建产品的接口,接口的实现由具体工厂负责。
具体工厂类J20Factory\Y20Factory\H20Factory: 继承自抽象工厂,实现创建对应具体产品对象的方法。
抽象产品类Aircraft:作为所有具体飞机的父类,抽象类。
具体产品类J20\Y20\H20:具体工厂类创建的就是这些类的实例。
定义具体工厂要实现哪些接口
1
2
3
4
5
6
|
class AircraftFactory {
public:
virtual Aircraft* create() = 0;
virtual ~AircraftFactory() = 0;
};
AircraftFactory::~AircraftFactory() {}
|
实现对应的接口,一个工厂高速生产单一产品
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
class J20Factory :public AircraftFactory {
public:
Aircraft* create() {
return new J20();
}
~J20Factory() {}
};
class Y20Factory :public AircraftFactory {
public:
Aircraft* create() {
return new Y20();
}
~Y20Factory() {}
};
class H20Factory :public AircraftFactory {
public:
Aircraft* create() {
return new H20();
}
~H20Factory() {}
};
|
就是一个父类抽象类,父类指针可以指向所有子类对象,返回值什么的用父类指针,调用的时候由于多态调用具体的子类的行为
1
2
3
4
5
|
class Aircraft {
public:
virtual ~Aircraft() = 0; // 基类的析构函数要为virtual
virtual void show() = 0; // 子类进行具体实现
};
|
继承自抽象产品类,定义每个具体产品的行为
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
class J20 : public Aircraft {
public:
void show() {
std::cout << "J20" << std::endl;
}
~J20() {}
};
class Y20 : public Aircraft {
public:
void show() {
std::cout << "Y20" << std::endl;
}
~Y20() {}
};
class H20 : public Aircraft {
public:
void show() {
std::cout << "H20" << std::endl;
}
~H20() {}
};
|
- 想要那种产品,就先开设对应产品线
- 用产品线生产源源不断的产品
- 使用产品
- 释放资源
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
int main() {
/* ============ 生产H20 ============ */
AircraftFactory* H20Producer = new H20Factory(); // 开设产品线
Aircraft* myH20 = H20Producer->create(); // 生产产品
myH20->show(); // 使用产品
// 释放资源
delete H20Producer;
delete myH20;
/* ============ 生产J20 ============ */
AircraftFactory* J20Producer = new J20Factory(); // 开设产品线
Aircraft* myJ20 = J20Producer->create(); // 生产产品
myJ20->show(); // 使用产品
// 释放资源
delete J20Producer;
delete myJ20;
return 0;
}
|
H20
J20
- 遵循了开闭原则
相比于刚才的简单工厂结构,如果想要开辟新的生产线,不会动到核心类AircraftFactory,只需要自己新写一个类比如Z20,然后继承自抽象父类,即可建成新的工厂。对于新的产品来说也是这样,只需实现新的产品类Z20,继承自抽象父类即可。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
/* ======== 新增产品Z20 ======== */
class Z20 :public Aircraft {
public:
void show() {
std::cout << "Z20" << std::endl;
}
~Z20() {}
};
/* ======== 新增工厂生产Z20 ======== */
class Z20Factory :public AircraftFactory {
public:
Aircraft* create() {
return new Z20();
}
~Z20Factory() {}
};
|
- 每新增一个产品,就需要增加一个对应的产品的具体工厂类。相比简单工厂模式而言,工厂方法模式需要更多的类定义,增加了代码的复杂性。
- 一条生产线只能一个产品。
军工厂产线升级(具体工厂能生产更多东西,不是单一产品),不止生产飞行器了,现在还能产飞行器配套的对空导弹或者对地高爆弹。
抽象工厂类AircraftFactory:工厂方法模式的核心类,是抽象类、接口类,所有具体工程的父类。提供具体创建产品的接口,接口的实现由具体工厂负责。
具体工厂类J20Factory\Y20Factory\H20Factory: 继承自抽象工厂,实现创建对应具体产品对象的方法。
抽象产品类Aircraft\Dynamite:作为所有具体飞机的父类,作为所有配套导弹的父类,抽象类。
具体产品类J20\Y20\H20\J20Missile\H20Bomb:具体工厂类创建的就是这些类的实例。
定义具体工厂要实现哪些接口
区别于工厂方法模式,既然每个具体工厂可以生产不止一样东西,那么接口类也要添加好对应的接口
1
2
3
4
5
6
7
|
class AircraftFactory {
public:
virtual Aircraft* createAircraft() = 0; // 生产飞行器
virtual Dynamite* createDynamite() = 0; // 生产配套弹药
virtual ~AircraftFactory() = 0;
};
AircraftFactory::~AircraftFactory() {}
|
实现父类的接口,现在一个工厂不是生产单一的产品了,能生产战机和配套的弹药。
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
|
class J20Factory :public AircraftFactory {
public:
Aircraft* createAircraft() {
return new J20();
}
Dynamite* createDynamite() {
return new J20Missile();
}
~J20Factory() {}
};
class Y20Factory :public AircraftFactory {
public:
Aircraft* createAircraft() {
return new Y20();
}
Dynamite* createDynamite() {
return NULL;
}
~Y20Factory() {}
};
class H20Factory :public AircraftFactory {
public:
Aircraft* createAircraft() {
return new H20();
}
Dynamite* createDynamite() {
return new H20Bomb();
}
~H20Factory() {}
};
|
现在有两种产品,那么一共需要两个抽象产品类,飞行器类和弹药类。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
// 飞行器接口类
class Aircraft {
public:
virtual ~Aircraft() = 0; // 基类的析构函数要为virtual
virtual void show() = 0; // 子类进行具体实现
};
Aircraft::~Aircraft() {}
// 弹药接口类
class Dynamite {
public:
virtual void show() = 0;
virtual ~Dynamite() = 0;
};
Dynamite::~Dynamite() {}
|
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
|
class J20 : public Aircraft {
public:
void show() {
std::cout << "J20" << std::endl;
}
~J20() {}
};
class Y20 : public Aircraft {
public:
void show() {
std::cout << "Y20" << std::endl;
}
~Y20() {}
};
class H20 : public Aircraft {
public:
void show() {
std::cout << "H20" << std::endl;
}
~H20() {}
};
// J20的导弹
class J20Missile :public Dynamite {
void show() {
std::cout << "Build for J20" << std::endl;
}
~J20Missile() {}
};
// H20的炸弹
class H20Bomb :public Dynamite {
void show() {
std::cout << "Build for H20" << std::endl;
}
~H20Bomb() {}
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
int main() {
// 实例化H20的工厂
AircraftFactory* H20Producer = new H20Factory();
// H20的工厂生产出H20
Aircraft* myH20 = H20Producer->createAircraft();
// H20的工厂生产出配套炸药
Dynamite* myH20Bomb = H20Producer->createDynamite();
myH20->show(); // 使用产品
myH20Bomb->show();
// 释放资源
delete H20Producer;
delete myH20;
delete myH20Bomb;
return 0;
}
|
H20
Build for H20
- 相比于之前的工厂方法模式一个工厂单一产品,抽象工厂模式可以生产出一组相互依赖的产品,保证了产品族的一致性,比如J20的导弹不会装到H20上去,J20和他的导弹是同一个产品族,具有依赖关系。
- 微妙地遵循了开闭关系。如果想要新增具体产品,比如说加个Z20和对应的导弹,那么确实不需要更改到抽象工厂类。但是如果要新增产品类型,比如说飞行员
pilot,那么抽象工厂类也要加入新的接口createPilot()。
- 跟之前工厂方法模式一样,每新增一个产品,就需要增加一个对应的产品的具体工厂类。增加了代码的复杂性。
可以注意到之前实现的代码都需要我们在使用完产品之后主动释放对象,可以使用智能指针来替代原始指针,避免手动管理内存。
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
|
#include <iostream>
#include <memory>
// 飞行器基类
class Aircraft {
public:
virtual ~Aircraft() = 0; // 基类的析构函数要为virtual
virtual void show() = 0; // 子类进行具体实现
};
Aircraft::~Aircraft() {}
// J20飞行器
class J20 : public Aircraft {
public:
void show() override {
std::cout << "J20" << std::endl;
}
~J20() {}
};
// Y20飞行器
class Y20 : public Aircraft {
public:
void show() override {
std::cout << "Y20" << std::endl;
}
~Y20() {}
};
// H20飞行器
class H20 : public Aircraft {
public:
void show() override {
std::cout << "H20" << std::endl;
}
~H20() {}
};
// 弹药接口类
class Dynamite {
public:
virtual void show() = 0;
virtual ~Dynamite() = 0;
};
Dynamite::~Dynamite() {}
// J20的导弹
class J20Missile : public Dynamite {
void show() override {
std::cout << "Build for J20" << std::endl;
}
~J20Missile() {}
};
// H20的炸弹
class H20Bomb : public Dynamite {
void show() override {
std::cout << "Build for H20" << std::endl;
}
~H20Bomb() {}
};
// 抽象工厂类
class AircraftFactory {
public:
virtual std::unique_ptr<Aircraft> createAircraft() = 0; // 生产飞行器
virtual std::unique_ptr<Dynamite> createDynamite() = 0; // 生产配套弹药
virtual ~AircraftFactory() = 0;
};
AircraftFactory::~AircraftFactory() {}
// J20工厂
class J20Factory : public AircraftFactory {
public:
std::unique_ptr<Aircraft> createAircraft() override {
return std::make_unique<J20>();
}
std::unique_ptr<Dynamite> createDynamite() override {
return std::make_unique<J20Missile>();
}
~J20Factory() {}
};
// Y20工厂
class Y20Factory : public AircraftFactory {
public:
std::unique_ptr<Aircraft> createAircraft() override {
return std::make_unique<Y20>();
}
std::unique_ptr<Dynamite> createDynamite() override {
return nullptr;
}
~Y20Factory() {}
};
// H20工厂
class H20Factory : public AircraftFactory {
public:
std::unique_ptr<Aircraft> createAircraft() override {
return std::make_unique<H20>();
}
std::unique_ptr<Dynamite> createDynamite() override {
return std::make_unique<H20Bomb>();
}
~H20Factory() {}
};
int main() {
/* ============ 生产H20 ============ */
std::unique_ptr<AircraftFactory> H20Producer = std::make_unique<H20Factory>();
std::unique_ptr<Aircraft> myH20 = H20Producer->createAircraft();
/* ============ 生产H20的炸药 ============ */
std::unique_ptr<Dynamite> myH20Bomb = H20Producer->createDynamite();
myH20->show(); // 使用产品
myH20Bomb->show();
return 0;
}
|