【设计模式】创建型模式

设计模式

学习笔记之C++设计模式——创建型模式
📑 【设计模式】结构型模式

📑 【设计模式】行为型模式

一、工厂模式

简单工厂模式

代码

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
#include <iostream>
#include "main.h"
using namespace std;
/*
定义一个水果抽象类。供具体水果实现,和工厂使用
*/
class Fruit {
public:
virtual void getName() = 0;

};
class Apple : public Fruit{
public:
virtual void getName() {
cout << "我是苹果" << endl;
}
};
class Banana : public Fruit {
public:
virtual void getName(){
cout << "我是香蕉" << endl;
}
};

//抽象的工厂类
class AbstractFactory
{
public:
virtual Fruit * createFruit() = 0;

};
//通过具体的某一产品的工厂生产某种产品
class AppleFactory : public AbstractFactory
{
public:
virtual Fruit * createFruit() {
return new Apple;
}
};
class BananaFactory : public AbstractFactory
{
public:
virtual Fruit * createFruit() {
return new Banana;
}
};
int main()
{
//来一个香蕉工厂
AbstractFactory * bananaFactory = new BananaFactory;
//给我来一个水果
Fruit * banana = bananaFactory->createFruit();
banana->getName();

delete bananaFactory;
delete banana;

AbstractFactory * appleFactory = new AppleFactory;
Fruit * apple = appleFactory->createFruit;
apple->getName();


system("pause");
return 0;
}

类图

工厂模式

工厂模式的优缺点

优点

  1. 不需要记住具体类名,甚至连具体参数都不用记忆。
  2. 实现了对象创建和使用的分离。
  3. 系统的可扩展性也就变得个非常好,无需修改接口和原类。

缺点

  1. 增加系统中类的个数,复杂度和理解度增加。

  2. 增加了系统的抽象性和理解难度。

二、抽象工厂模式

工厂方法模式通过引入工厂等级结构,解决了简单工厂模式中工厂类职责太重的问题,但由于工厂方法模式中的每个工厂只生产-产品,可能会导致系统中存在大量的工厂类,势必会增加系统的开销。此时,我们可以考虑将一些相关的产品组成一个"产品族”, 由同-个工厂来统-生产,这就是我们本文将要学习的抽象工厂模式的基本思想。

图例

抽象工厂模式

代码

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
#include <iostream>
#include "main.h"
using namespace std;
//抽象产品类 供具体产地产品实现
class AbstractApple {
public:
virtual void getName() = 0;
};
class AbstractBanana {
public:
virtual void getName() = 0;
};
class AbstractPear {
public:
virtual void getName() = 0;
};

class USAApple : public AbstractApple {
public:
virtual void getName() {
cout << "美国苹果" << endl;
}
};
class ChinaApple : public AbstractApple {
public:
virtual void getName() {
cout << "中国苹果" << endl;
}
};
class JapanApple : public AbstractApple {
public:
virtual void getName() {
cout << "日本苹果" << endl;
}
};
class USABanana : public AbstractBanana {
public:
virtual void getName() {
cout << "美国香蕉" << endl;
}
};
class ChinaBanana : public AbstractBanana {
public:
virtual void getName() {
cout << "中国香蕉" << endl;
}
};
class JapanBanana : public AbstractBanana {
public:
virtual void getName() {
cout << "日本香蕉" << endl;
}
};
class USAPear : public AbstractPear {
public:
virtual void getName() {
cout << "美国鸭梨" << endl;
}
};
class ChinaPear : public AbstractPear {
public:
virtual void getName() {
cout << "中国鸭梨" << endl;
}
};
class JapanPear : public AbstractPear {
public:
virtual void getName() {
cout << "日本鸭梨" << endl;
}
};
//抽象的工厂类,供具体产品族的实现
class AbstractFactory {
public:
virtual AbstractApple * creatApple() = 0;
virtual AbstractBanana * creatBanana() = 0;
virtual AbstractPear * creatPear() = 0;
};
//具体的工厂
class USAFactory : public AbstractFactory {
public:
virtual AbstractApple * creatApple() {
return new USAApple;
}
virtual AbstractBanana * creatBanana() {
return new USABanana;
}
virtual AbstractPear * creatPear() {
return new USAPear;
}
};
class ChinaFactory : public AbstractFactory {
public:
virtual AbstractApple * creatApple() {
return new ChinaApple;
}
virtual AbstractBanana * creatBanana() {
return new ChinaBanana;
}
virtual AbstractPear * creatPear() {
return new ChinaPear;
}
};
class JapanFactory : public AbstractFactory {
public:
virtual AbstractApple * creatApple() {
return new JapanApple;
}
virtual AbstractBanana * creatBanana() {
return new JapanBanana;
}
virtual AbstractPear * creatPear() {
return new JapanPear;
}
};


int main()
{
//现在要准备一个 中国的苹果,中国的香蕉
AbstractApple *AA = NULL;
AbstractBanana *AB = NULL;
AbstractPear *AP = NULL;

AbstractFactory *factory = NULL;
factory = new ChinaFactory;
//中国的苹果
AA = factory->creatApple();
//中国的香蕉
AB = factory->creatBanana();
AP = factory->creatPear();

AA->getName();
AB->getName();
AP->getName();

delete AA;
delete AB;
delete AP;
delete factory;

system("pause");
return 0;
}

抽象工厂模式不符合“开闭原则”

抽象工厂模式的优缺点

优点:

  1. 拥有工厂方法模式的优点
  2. 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象
  3. 增加新的产品族很方便,无需修改已有系统,符合“开闭原则”。

缺点:

  1. 增加新的产品结构麻烦,需要对原有系统进行较大的修改,甚至需要修改抽象层代码,带来较大的不便,违背了“开闭原则”。

抽象模式的应用:可以自己写一个计算机产品相关

简单工厂模式 + “开闭原则” = 工厂方法模式

工厂方法模式 + “产品族” = 抽象工厂模式

简单工厂模式(规模较小的模型)

工厂方法模式(中等)

抽象工厂模式(复杂的)

借鉴了《Easy搞定设计模式》

三 单例模式

保证一个类、只有一个实例存在,同时提供能对该实例加以访问的的全局访问方法。

三个要点:

一是某个类只能有一个实例;

二是它必须自行创建这个实例;

三是它必须自行向整个系统提供这个实例。

image-20201119180254196

角色和职责

Singleton(单例):在单例类的内部实现只生成一个实例,同时是他提供一个静态的getInstance()方法,让客户可以访问他的唯一实例;为了防止在外部对其实例化,将其构造函数设计为私有;在单例类内部定义了一个Singleton类型的静态对象,作为外部共享的唯一实例。

单例模式的使用步骤

  1. 构造函数私有化
  2. 提供一个全局的静态方法(全局访问点) 来获取单例对象。
  3. 在类中定义一个静态指针,指向本类的变量的静态变量指针

饿汉模式

理解

主要就是为了只让类只有一个实例而把构造函数私有化。定义一个全局的静态实例。

代码

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
#include <iostream>
using namespace std;
/*
三个步骤:
1.构造函数私有化(为了不让在类的外部再创建多余的实例)
2.提供一个全局的静态类指针指向唯一实例
3.提供一个全局的静态函数获取实例
*/
class Singleton {
public:
// 静态类函数 返回静态实例
static Singleton * getInstance() {
return instance;
}

private:
//不让类的外部创建实例
Singleton() {
Singleton *single = getInstance();
}

Singleton getsingle() {

}
static Singleton * instance; //指向本类的唯一实例指针
};
//静态类变量在类外初始化
Singleton*Singleton::instance = new Singleton;

int main()
{
//通过getInstance()获取实例
Singleton * s1 = Singleton::getInstance();
system("pause");
return 0;
}

懒汉模式

在程序执行期间再去判断是否需要实例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Singleton1 {
public:
//提供一个返回实例的方法
static Singleton1 * getInstance() {
// 不确定程序在编译期间是否需要实例
// 如果是多线程下,需要在这里加锁
if (instance1 == NULL) {
instance1 = new Singleton1;
}
// 释放锁
cout << "Singleton1" << endl;
return instance1;
}
private:
Singleton1() {
}
static Singleton1 *instance1;
};
//懒汉式的初始化方式 饿汉式在初始化时已经指向了singleton
Singleton1 * Singleton1::instance1 = NULL;

针对单例模式去判断是否是同一实例

1
2
3
4
5
6
Singleton *s1 = Singleton::getinstace();
Singleton *s2 = Singleton::getinstace();
if (s1 == s2 )
cout << "s1 == s2" << endl;
else
cout << "s1 != s2" << endl;

单例模式的应用——打印机

用单例模式实现一个打印机程序,用以记录打印的次数和内容

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
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
class Printer {
public:
static Printer * getinstance() {
return instance;
}
void print(string text) {
cout << "打印的内容为:" << text << endl;
sequence++;
cout << "打印机今天使用了" << sequence << "次" << endl;
}
static int getSequence() {
return sequence;
}
private:
// 定义一个类去析构单例
class Garbo {
private:
~Garbo() {
if (instance != NULL) {
delete instance;
}
}
};
static Garbo garbo; // 在静态区域开辟一个对象,Garbo
static int sequence;
static Printer * instance;
};
int Printer::sequence = 0;
Printer *Printer::instance = new Printer;
Printer::Garbo Printer::garbo;

int main()
{
//三个peple使用打印机
Printer * p1 = Printer::getinstance();
p1->print("亿封简历");

Printer *p2 = Printer::getinstance();
p2->print("一份工作汇报");

Printer *p3 = Printer::getinstance();
p3->print("离职申请");

system("pause");
return 0;
}

以上就是几种常见的创建型设计模式。


【设计模式】创建型模式
https://hodlyounger.github.io/A_内功/B_设计模式/【设计模式】创建型模式/
作者
mingming
发布于
2023年12月25日
许可协议