常用设计模式

常用设计模式

单例模式

定义:一个类不管创建多少次对象,永远只能得到该类型一个对象的实例,常用到的如,日志模块,数据库模块

分类:

  • 饿汉式单例模式:还没有获取实例对象,实例对象就已经产生了
  • 懒汉式单例模式:唯一的实例对象直到第一次获取时才创建
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//饿汉式单例:
class Singleton
{
public:
static Singleton * getInstance()//#3 定义静态成员方法(不需要通过对象调用),获取类唯一实例对象的接口方法
{
return &instance;
}

private:
static Singleton instance; // #2 定义一个唯一的类的实例对象,位于数据段

Singleton() // #1 构造函数私有化
{
}

Singleton(const Singleton& ) = delete;
Singleton& operator=(const Singleton&) = delete;
};

Singleton Singleton::instance; //静态成员变量类内声明类外定义

单例的饿汉实现是线程安全的,因为对象在使用前就已经创建出来了。

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
//懒汉式单例:
class Singleton
{
public:
static Singleton * getInstance()
{
if(instance == nullptr) {
instance = new Singleton();
}
return instance;
}

private:
static Singleton* instance;

Singleton()
{
}

Singleton(const Singleton& ) = delete;
Singleton& operator=(const Singleton&) = delete;
};

Singleton* Singleton::instance = nullptr;
//未调用getInstance时,instance一直为nullptr
//当调用getInstance时,生成唯一对象并为instance赋值

上述懒汉式单例模式并非线程安全,getInstance函数并非可重入函数。若要改为线程安全的懒汉式单例模式只需修改getInstance函数

1
2
3
4
5
6
7
8
9
10
11
static Singleton * getInstance()
{
if(instance == nullptr) {
std::lock_guard<std::mutex> guard(mtx); //保证只能实例化一个对象
if(instance == nullptr) {
instance = new Singleton();
}
}
return instance;
}
static Singleton* volatile instance; //防止线程缓冲影响

全局变量、文件域的静态变量和类的静态成员变量在main执行之前的静态初始化过程中分配内存并初始化;局部静态变量(一般为函数内的静态变量)在第一次使用时分配内存并初始化。这里的变量包含内置数据类型和自定义类型的对象

非局部静态变量一般在main执行之前的静态初始化过程中分配内存并初始化,可以认为是线程安全的;

局部静态变量在编译时,在g++中通过查看汇编指令发现已经添加了线程互斥操作,故是线程安全的

故懒汉式单例模式也可以改写为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Singleton
{
public:
static Singleton * getInstance()
{
static Singleton instance;
return &instance;
}
private:
static Singleton* volatile instance;
Singleton()
{
}
Singleton(const Singleton& ) = delete;
Singleton& operator=(const Singleton&) = delete;
};

工厂模式

定义:

这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。简单来说,使用了C++多态的特性,将存在继承关系的类,通过一个工厂类创建对应的子类(派生类)对象。在项目复杂的情况下,可以便于子类对象的创建。

分类:

  • 简单工厂:simple factory
  • 工厂方法:factory method
  • 抽象工厂:abstract factory
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
//简单工厂
class Car {
public:
explicit Car(string name)
: _name(std::move(name)) {}
virtual void show() = 0;
protected:
string _name;
};

class BMW : public Car {
public:
explicit BMW(string name)
: Car(std::move(name)) {}

void show() override {
cout << "获取BMW" << _name << endl;
}
};

class Audi : public Car {
public:
explicit Audi(string name)
: Car(std::move(name)) {}
void show() override {
cout << "获取AUdi" << _name << endl;
}
};

enum class CarType {
BMW, AUDI
};

class SimpalFactory { //工厂类
public:
Car *createCar(CarType ct) {
switch (ct) {
case CarType::BMW:
return new BMW("X1");
break;
case CarType::AUDI:
return new Audi("A6");
default:
cerr << "Usage argv is not right" << endl;
}
}
};

int main() {
/*
SimpalFactory factory;
Car *bmw = factory.createCar(CarType::BMW);
Car *audi = factory.createCar(CarType::AUDI);
bmw->show(); delete bmw;
audi->show(); delete audi;
*/
unique_ptr<SimpalFactory> factory(new SimpalFactory());
unique_ptr<Car> p1(factory->createCar(CarType::BMW));
}

简单工厂模式在扩展时要修改许多东西,当通过多态增加一种汽车时,工厂类对应的枚举值要增加,要修改工厂类中createCar函数。比较麻烦不符合对扩展关闭的原则,改进为工厂方法:

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
//工厂方法:
class Car {
public:
explicit Car(string name)
: _name(std::move(name)) {}
virtual void show() = 0;
protected:
string _name;
};
class BMW : public Car {
public:
explicit BMW(string name)
: Car(std::move(name)) {}
void show() override {
cout << "获取BMW" << _name << endl;
}
};
class Audi : public Car {
public:
explicit Audi(string name)
: Car(std::move(name)) {}
void show() override {
cout << "获取AUdi" << _name << endl;
}
};
class Factory {
public:
virtual Car *createCar(string name) = 0;
};
class BMWFactory : public Factory {
public:
Car *createCar(string name) override {
return new BMW(name);
}
};
class AudiFactory : public Factory {
public:
Car * createCar(string name) override
{
return new Audi(name);
}
};
int main()
{
unique_ptr<Factory> bmwfty(new BMWFactory());
unique_ptr<Factory> audifty(new AudiFactory());
unique_ptr<Car> p1(bmwfty->createCar("X6"));
unique_ptr<Car> p2(audifty->createCar("A6"));
p1->show();
p2->show();
return 0;
}

对于工厂方法,当扩展时,只需继承Car通过多态实现实体后,继承Factory通过多态实现createCar。

但是实际情况并非如此,一个工厂可能及生产手机又生产耳机或者生产音响,对于工厂方法来说,每个工厂只能生产一个物品,当物品多且相似时这种设计是不好的,因此产生了抽象工厂

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
//抽象工厂
class Car {
public:
explicit Car(string name)
: _name(std::move(name)) {}
virtual void show() = 0;
protected:
string _name;
};
class BMW : public Car {
public:
explicit BMW(string name)
: Car(std::move(name)) {}

void show() override { cout << "获取BMW" << _name << endl; }
};
class Audi : public Car {
public:
explicit Audi(string name)
: Car(std::move(name)) {}

void show() override { cout << "获取AUdi" << _name << endl; }
};
class Light {
public:
virtual void show() = 0;
};
class bmwLight : public Light {
public:
void show() override { cout << "BMW light" << endl; }
};
class audiLight : public Light {
public:
void show() override { cout << "Audi light" << endl; }
};

//抽象方法
class AbstractFactory {
public:
virtual Car *createCar(string name) = 0; //创建汽车
virtual Light *createCarLight() = 0; //创建灯
};
class BMWFactory : public AbstractFactory {
public:
Car *createCar(string name) override {
return new BMW(name);
}
Light *createCarLight() override {
return new bmwLight;
}
};
class AudiFactory : public AbstractFactory {
public:
Car *createCar(string name) override {
return new Audi(name);
}
Light *createCarLight() override {
return new audiLight;
}
};
int main() {
unique_ptr<AbstractFactory> bmwfty(new BMWFactory);
unique_ptr<AbstractFactory> Audifty(new AudiFactory);
unique_ptr<Car> p1(bmwfty->createCar("x1"));
unique_ptr<Car> p2(Audifty->createCar("A6"));
unique_ptr<Light> p3(bmwfty->createCarLight());
unique_ptr<Light> p4(Audifty->createCarLight());
p1->show();p2->show();p3->show();p4->show();
return 0;
}

但是抽象工厂也存在一些问题,当bmw工厂存在特殊的方法(其他工厂没有时),此时需要在Abstractory基类中添加纯虚函数,但是只有bmw工厂给出了具体的实现,其他工厂必须重写否则无法通过编译,一般实现为空

简单工厂把对象的创建封装在一个接口函数里面,通过传入不同的标志,返回创建的对象,客户不用自己new对象,不用了解对象创建的细节

工厂方法Factory基类提供了一个纯虚函数(创造产品),定义派生类(具体产品的工厂)负责创建对应的产品,可以做到不同的产品在不同的工厂里创建

抽象工厂把有关联的属于一个产品族的所有产品创建接口函数,放在一个抽象工厂中,派生类(具体产品的工厂)应该负责创建该产品族里的所有产品

代理模式

通过代理类来控制实际对象的访问权限

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
class VideoSite {
public:
virtual void freeMovie() = 0; //免费电影
virtual void vipMovie() = 0; //vip电影
virtual void ticketMovie() = 0; //用卷购买的电影
};

class FixbugVideoSite : public VideoSite { //FixbugVideoSite 中存在所有的实现
public:
virtual void freeMovie() {
cout << "freeMovie" << endl;
}

virtual void vipMovie() {
cout << "vipMovie" << endl;
}

virtual void ticketMovie() {
cout << "ticketMovie" << endl;
}
};

class FreeVideoSiteProxy : public VideoSite { //普通用户代理类
public:
FreeVideoSiteProxy() { pVideo = new FixbugVideoSite; } //指向实现类
~FreeVideoSiteProxy() { delete pVideo; }

virtual void freeMovie(){ //实现访问控制
pVideo->freeMovie();
}
virtual void vipMovie() {
cout<<"vip视频,您无权访问"<<endl;
}
virtual void ticketMovie(){
cout<<"需要买卷"<<endl;
}
private:
VideoSite *pVideo; //存有基类指针
//FixbugVideoSite video 通过组合的方式也可以,但是这这能代理FixbugVideoSite类,降低了灵活性,
};

class vipVideoSiteProxy : public VideoSite{ //vip用户代理类
public:
vipVideoSiteProxy(){ p = new FixbugVideoSite ;}
~vipVideoSiteProxy() { delete p; }

virtual void freeMovie(){ //实现访问控制
p->freeMovie();
}
virtual void vipMovie() {
p->vipMovie();
}
virtual void ticketMovie(){
cout<<"需要买卷"<<endl;
}
private:
VideoSite* p;
};

void watchMovie(unique_ptr<VideoSite> & ptr){
ptr->freeMovie();
ptr->vipMovie();
ptr->ticketMovie();
}

int main() {

unique_ptr<VideoSite> p1(new FreeVideoSiteProxy); //直接访问代理对象,而非实际对象
unique_ptr<VideoSite> p2(new vipVideoSiteProxy);
//p1->freeMovie(); p1->vipMovie(); p1->ticketMovie();
//p2->freeMovie(); p2->vipMovie(); p2->ticketMovie();
watchMovie(p1);
watchMovie(p2);
}

装饰器模式

装饰器模式是为了增加现有类的功能。但是增加现有类功能的另一个方法是增加一个子类

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
class Car {      //抽象基类
public:
virtual void show() = 0;
};
//三个实体的派生类
class BMW : public Car {
public:
void show() {
cout << "这是一个BMW汽车,配置有:基本配置" << endl;
}
};

class Audi : public Car {
public:
void show() {
cout << "这是一个Audi汽车,配置有:基本配置" << endl;
}
};

class Benz : public Car {
public:
void show() {
cout << "这是一个Benz汽车,配置有:基本配置" << endl;
}
};


class ConcreteDecorator01 : public Car
{
public:
ConcreteDecorator01(Car* p) : pCar(p) {}
void show()
{
pCar->show();
cout<<"新增方法01"<<endl;
}
private:
Car* pCar;
};

class ConcreteDecorator02 : public Car
{
public:
ConcreteDecorator02(Car* p) : pCar(p) {}
void show()
{
pCar->show();
cout<<"新增方法02"<<endl;
}

private:
Car * pCar;
};

int main()
{
Car * p1 = new ConcreteDecorator01(new BMW()); //对具有普通功能进行装饰,使其新增功能1
p1->show();
Car * p2 = new ConcreteDecorator01(new ConcreteDecorator02(new BMW));
p2->show();
}

适配器模式

让不兼容的接口可以在一起工作

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
class VGA {
public:
virtual void play() = 0;
std::string getType() { return "VGA"; }
};

class TV01 : public VGA {
public:
void play() { cout << "通过VGA 接口连接投影 并播放" << endl; }
};

class Computer //只支持VGA接口的电脑类
{
public:
void PlayVideo(VGA *pVGA) //由于只支持VGA接口,故参数只能是VGA的指针或引用
{
pVGA->play();
}
};

class HDMI {
public:
virtual void play() = 0;
};

class TV02 : public HDMI {
public:
void play() override { cout << "通过HDMI 接口连接投影 并播放" << endl; }
};

//由于电脑(VGA)投影仪(HDMI)无法直接相连
// 需要使用适配器,将 VGA 信号转换为 HDMI 信号
class VGA2HDMI : public VGA {
public:
VGA2HDMI(HDMI *p) : pHDMI(p) {}

void play() override {
pHDMI->play();
}

private:
HDMI *pHDMI;
};

int main() {
Computer c;
c.PlayVideo(new TV01);
c.PlayVideo(new VGA2HDMI(new TV02()));
}

观察者模式

主要关注的是对象的一对多关系,也就是多个对象都依赖一个对象,当该对象的状态发生改变时,其他对象都能接受到相应的通知

如:我们有一组数据,可以通过这组数据生成对应的曲线图,柱状图,圆饼图。当数据改变时,这三个图都要发生变化

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
// 观察者抽象类
class Observer
{
public:
// 处理消息的接口
virtual void handle(int msgid) = 0;
};
// 第一个观察者实例
class Observer1 : public Observer
{
public:
void handle(int msgid)
{
switch (msgid)
{
case 1:
cout << "Observer1 recv 1 msg!" << endl;
break;
case 2:
cout << "Observer1 recv 2 msg!" << endl;
break;
default:
cout << "Observer1 recv unknow msg!" << endl;
break;
}
}
};
// 第二个观察者实例
class Observer2 : public Observer
{
public:
void handle(int msgid)
{
switch (msgid)
{
case 2:
cout << "Observer2 recv 2 msg!" << endl;
break;
default:
cout << "Observer2 recv unknow msg!" << endl;
break;
}
}
};
// 第三个观察者实例
class Observer3 : public Observer
{
public:
void handle(int msgid)
{
switch (msgid)
{
case 1:
cout << "Observer3 recv 1 msg!" << endl;
break;
case 3:
cout << "Observer3 recv 3 msg!" << endl;
break;
default:
cout << "Observer3 recv unknow msg!" << endl;
break;
}
}
};

// 主题类
class Subject
{
public:
// 给主题增加观察者对象
void addObserver(Observer* obser, int msgid)
{
_subMap[msgid].push_back(obser);
/*auto it = _subMap.find(msgid);
if (it != _subMap.end())
{
it->second.push_back(obser);
}
else
{
list<Observer*> lis;
lis.push_back(obser);
_subMap.insert({ msgid, lis });
}*/
}
// 主题检测发生改变,通知相应的观察者对象处理事件
void dispatch(int msgid)
{
auto it = _subMap.find(msgid);
if (it != _subMap.end())
{
for (Observer *pObser : it->second)
{
pObser->handle(msgid);
}
}
}
private:
unordered_map<int, list<Observer*>> _subMap;
};

int main()
{
Subject subject;
Observer *p1 = new Observer1();
Observer *p2 = new Observer2();
Observer *p3 = new Observer3();

subject.addObserver(p1, 1);
subject.addObserver(p1, 2);
subject.addObserver(p2, 2);
subject.addObserver(p3, 1);
subject.addObserver(p3, 3);

int msgid = 0;
for (;;)
{
cout << "输入消息id:";
cin >> msgid;
if (msgid == -1)
break;
subject.dispatch(msgid);
}
return 0;
}