声明:本文记录c++ 设计模式及示例代码

1. 面向对象设计原则

总原则:减少变化带来的影响

  1. 单一职责原则(SRP)

  2. 开放封闭原则(OCP)

  • 对扩展开放,对更改封闭。
  1. 里氏替换原则(LSP:Liskov substitution principle)
  • 子类必须能够替换它们的基类(IS-A)。
  1. 接口隔离原则(ISP:Interface Segregation Principle)
  • 不应该强迫客户程序依赖它们不用的方法。
  • 接口应该小而完备。
  1. 依赖倒置原则(DIP)
  • 高层模块(稳定)不应该依赖于低层模块(变化),二者都应该依赖于抽象(稳定) 。
  • 抽象(稳定)不应该依赖于实现细节(变化) ,实现细节应该依赖于抽象(稳定)。
  • 例如, 当我们需要邮箱联系时如图, 此时使用DIP 方式,当我们需要添加或修改邮箱时不必关心上层的改动
    DIP
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    //not DIP
    class People{
    public:
    bool Contact(GMail);
    bool Contact(QMail);
    ...
    };

    //DIP
    class IMail{
    public:
    virtual bool FormMessage() = 0;
    };

    class People{
    public:
    bool Contact(IMail mail);
    };

以上速记为SOLID,有些地方说七大原则的另外两个是迪米特法则和组合优先原则

2.设计模式的分类总览

本小节内容主要参考自参考资料①

2.1 设计模式的分类
  1. 按目的分为:
  • 创建型:关注将对象的创建与使用分离, 封装创建细节
  • 结构型:关注如何将类或对象组合, 以此获取更强大的功能
  • 行为型:关注类或对象之间的相互协作
  1. 按作用范围分为:
  • 类模式:处理类与子类之间的关系,在编译时便确定下来了
  • 对象模式:处理对象之间的关系
2.2 设计模式模式概览

下划线表示该模式可以为类模式, 其余为对象模式

分类 名称 描述
创建型 工厂方法 定义一用于创建产品的接口,由子类决定生产什么产品
抽象工厂模式 提供一个创建产品族的接口,其每个子类(工厂)生产一系列相关的产品
原型模式 将对象作为原型,克隆出多个和原型类似的新实例,以此加速对象的创建
单例模式 提供某类的唯一对象的唯一全局访问点
构建器模式 将复杂对象分解成多个部分,根据需要分别创建,然后构建成该复杂对象
结构型 适配器 将类的接口转换成目的接口,使得原本不兼容的接口可以协同
桥接模式 将抽象与实现分离(通过组合将继承树进行拆分),使它们可以独立变化
组合模式 将对象组合成树状层次结构,使用户对单个对象和组合对象的使用一致
装饰模式 动态的给对象增加一些职责,增加其额外的功能
外观模式 对外为多个复杂的子系统提供一个一致的接口,简化系统的使用
享元模式 运用共享技术来有效地支持大量细粒度对象的复用,例如文章共享一个文字
代理模式 为对象提供一种代理以控制对该对象的访问,限制、增强或修改该对象的一些特性
行为型 责任链模式 把请求从链中的一个对象传到下一个对象,直到请求被响应为止,从而去除对象之间的耦合
命令模式 将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开
解释器模式 提供如何定义语言的方法,以及对语言句子的解释方法
迭代器模式 提供一种方法来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示
中介模式 定义一个中介对象来简化原有对象之间的交互关系,降低系统中对象间的耦合度,使原有对象之间不必相互了解
备忘录模式 在不破坏封装性的前提下,获取并保存一个对象的内部状态,以便以后恢复它
观察者模式 多个对象间存在一对多关系,当一个对象发生改变时,把这种改变通知给其他多个对象,从而影响其他对象的行为
状态模式 允许一个对象在其内部状态发生改变时改变其行为能力
策略模式 定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的改变不会影响使用算法的客户
模板模式 定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤
访问者模式 为一个集合中的每个元素提供多种访问方式(将数据结构与数据操作分离)

3. 代码示例

本章为简单起见, 忽略了一些细节,比如

  • 没使用智能指针,需要自行留意内存泄漏问题,
  • 没有严格的定义Big five, 比如再不需要暴露的基类应当声明成protected等
  • c++ 没有专门的Inteface 关键字,故而这里也没有专门的留意, 自行斟酌需不需要纯接口而将公共成员挪至子类
    • 有一种做法是一个纯接口, 由一个抽象类继承,扩展子类基于此抽象类, 个人感觉这是有些麻烦的

3.1 创建型

3.1.1 工厂模式

场景:根据不同条件创建不同对象时考虑使用。
本节假设有以下产品, 并可能根据接口扩展

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 Shape{
public:
virtual void Draw() = 0;
virtual ~Shape(){}
};

class Circle: public Shape{
public:
void Draw(){printf("Cir");}
};

class Rectangle: public Shape{
public:
void Draw(){printf("Rec");}
};

class Color{
public:
virtual void Fill() = 0;
virtual ~Color(){}
};

class Red: public Color{
public:
void Fill(){printf("Red Fill\n");}
};

class Blue: public Color{
public:
void Fill(){printf("Blue Fill \n");}
};

3.1.1.1 简单工厂

simpleFac

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

enum SHAPE_TYPE{eCircle, eRectangle};
class ShapeFactory{
public:
Shape* CreateShape(SHAPE_TYPE type){
switch(type){
case eCircle:return new Circle;
case eRectangle: return new Rectangle;
}
}
};

//缺点:扩展性差, 当需要新加形状时需要修改工厂类, 违反OCP
int main(){
ShapeFactory fac;
fac.CreateShape(eCircle)->Draw();
return 0;
}
3.1.1.2 一般工厂

fac

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

class ShapeFactory{
public:
virtual Shape* CreateShape() = 0;
virtual ~ShapeFactory(){}
};

class CircleFac: public ShapeFactory{
public:
Shape* CreateShape(){ return new Circle;}
};

class RectangleFac: public ShapeFactory{
public:
Shape* CreateShape(){ return new Rectangle;}
};

//缺点:每增加一个对应的产品就要新增一个对应的工厂
//一个工厂只能生产一个产品
int main(){
ShapeFactory* fac = new RectangleFac;
fac->CreateShape()->Draw();
return 0;
}
3.1.1.3 抽象工厂

absFac

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 Factory{
virtual Color* CreateColor() = 0;
virtual Shape* CreateShape() = 0;
virtual ~Factory(){}
};

class RedCircFactory{
public:
Color* CreateColor(){return new Red;}
Shape* CreateShape(){return new Circle;}
};

class BlueRectFactory{
public:
Color* CreateColor(){return new Blue;}
Shape* CreateShape(){return new Rect;}
};

//缺点:每增加一个产品族就要新增一个对应的工厂
//不需要系列产品或不构成系列产品时没必要使用抽象工厂
int main(){
Factory* fac = new RedCircFactory;
fac->CreateShape()->Draw();
fac->CreateColor()->Fill();
return 0;
}
3.1.1.4 模板工厂
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
//一般工厂方法利用模板将代码的生成交给编译器
template <class AbstractProduct_t>
class Factory
{
public:
virtual AbstractProduct_t *CreateProduct() = 0;
virtual ~Factory() {}
};

// 具体模板工厂类
// 模板参数:AbstractProduct_t 产品抽象类,ConcreteProduct_t 产品具体类
template <class AbstractProduct_t, class ConcreteProduct_t>
class Factory : public Factory<AbstractProduct_t>
{
public:
AbstractProduct_t *CreateProduct()
{
return new ConcreteProduct_t();
}
};

//缺点, 产品没有统一生产管理
int main(){
Factory<Shape, Circle> circleFac;
circleFac.CreateProduct()->Draw();

Factory<Shape, Rectangle> rectFac;
rectFac.CreateProduct()->Draw();

Factory<Color, Red> redFac;
redFac.CreateProduct()->Fill();
}

3.1.1.5 注册模板工厂
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
// 利用map来保存注册的产品工厂
template <class ProductType_t>
class ProductRegistrar
{
public:
// 获取产品对象抽象接口
virtual ProductType_t *CreateProduct() = 0;

protected:
IProductRegistrar() {}
virtual ~ProductRegistrar() {}

private:
ProductRegistrar(const ProductRegistrar &) = delete;
const ProductRegistrar &operator=(const ProductRegistrar &) = delete;
};

// 工厂模板类,用于获取和注册产品对象
template <class ProductType_t>
class ProductFactory
{
public:
static ProductFactory<ProductType_t> &Instance()
{
static ProductFactory<ProductType_t> instance;
return instance;
}

void RegisterProduct(IProductRegistrar<ProductType_t> *registrar, std::string name)
{
m_ProductRegistry[name] = registrar;
}

ProductType_t *GetProduct(std::string name)
{
if (m_ProductRegistry.find(name) != m_ProductRegistry.end())
{
return m_ProductRegistry[name]->CreateProduct();
}

return nullptr;
}

private:
ProductFactory() {}
~ProductFactory() {}

ProductFactory(const ProductFactory &) = delete;
const ProductFactory &operator=(const ProductFactory &) = delete;

std::map<std::string, IProductRegistrar<ProductType_t> *> m_ProductRegistry;
};

// 产品注册模板类,用于创建具体产品和从工厂里注册产品
template <class ProductType_t, class ProductImpl_t>
class ProductRegistrar : public IProductRegistrar<ProductType_t>
{
public:
// 构造函数,用于注册产品到工厂,只能显示调用
explicit ProductRegistrar(std::string name)
{
ProductFactory<ProductType_t>::Instance().RegisterProduct(this, name);
}

ProductType_t *CreateProduct()
{
return new ProductImpl_t();
}
};

int main(){
ProductRegistrar<Shape, Circle> a("Circ");
Shape *pCircle = ProductFactory<Shape>::Instance().GetProduct("Circ");
if(pCircle)pCircle->Draw();

ProductRegistrar<Shape, Rectangle> b("Rect");
Shape *pRect = ProductFactory<Shape>::Instance().GetProduct("Rect");
if(pRect)pRect->Draw();

ProductRegistrar<Color, Red> c("Red");
Color *pRed = ProductFactory<Color>::Instance().GetProduct("Red");
if(pRed)pRed->Fill();

return 0;
}

3.1.2 单例模式

场景: 全局共享同一实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//c++11 开始, 编译器保证静态变量初始化的安全性
class Singleton
{
private:
Singleton() {};
~Singleton() {};
Singleton(const Singleton&);
Singleton& operator=(const Singleton&);
public:
static Singleton& getInstance()
{
static Singleton instance;
return instance;
}
};
3.1.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
37
38
39
40
41
42
class Shape{
public:
virtual Shape* Clone() = 0;
virtual void Draw() = 0;
virtual void SetSeq(int seq){ _seq = seq; }
virtual ~Shape(){};
protected:
int _seq;
};

class Circle: public Shape{
public:
Circle():_name("circle"){}
Circle(const Circle& other){
_seq = other._seq;
_name = other._name;
//其他赋值
//当其他属性修改时, 客户端不必担心由此带来的修改, 只需要修改这里
}

virtual Shape* Clone() override {return new Circle(*this);}
void Draw() override {printf("%d, %s\n", _seq, _name.c_str());}

private:
//其他复杂属性
string _name;
};

int main(){
//拷贝(移动)构造或者拷贝(移动)赋值无法使用基类直接创建新的示例
Shape* circ = new Circle;
circ->SetSeq(0);

Shape* circ2 = circ -> Clone();
circ2->SetSeq(1);

circ->Draw();
circ2->Draw();

return 0;
}

3.1.4 构建器模式

场景:复杂对象的构建拆分成多个部分来构建, 组装的过程不需要经常变化,而各个分部却经常变化

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
class Shape{
public:
void Draw(){printf("%s,%s\n", _color.c_str(), _fill.c_str());}
void SetColor(string color){_color = color;}
void SetFill(string fill){_fill = fill;}
private:
string _color;
string _fill;
};

class Builder{//子类随意切换color, shape
public:
virtual void BuildFill() = 0;
virtual void BuildColor() = 0;
virtual Shape* GetRes() = 0;

virtual ~Builder(){}
protected:
Builder(){_shape = new Shape;}
Shape *_shape;
};

class CircleBuilder:public Builder{
public:
CircleBuilder(){}
void BuildFill()override{_shape->SetFill("circ");}
void BuildColor()override{_shape->SetColor("blue");}
Shape* GetRes()override{return _shape;}
};

class ShapeMaker{//区别于模板, 这是创建型
public:
explicit ShapeMaker(Builder *builder):_shapeBuilder(builder){}
Shape* make(){
_shapeBuilder->BuildFill();
_shapeBuilder->BuildColor();
return _shapeBuilder->GetRes();
}
private:
Builder* _shapeBuilder;
};

int main(){
Builder* builder = new CircleBuilder;
ShapeMaker maker(builder);
maker.make()->Draw();
return 0;
}

3.2 结构型

3.2.1 适配器模式

场景:一个接口转为另外一个接口
adapter

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 Target{
public:
virtual void FuncA(){printf("A\n");}
virtual ~Target(){}
};

class Adaptee{
public:
virtual void FuncB(){printf("B\n");}
virtual ~Adaptee(){}
};

class Adapter:public Target{
public:
explicit Adapter(Adaptee *adaptee):_adaptee(adaptee){}
void FuncA()override{_adaptee->FuncB();}
private:
Adaptee *_adaptee;
};

int main(){
Adaptee *adaptee = new Adaptee;
Target* target = new Adapter(adaptee);
target->FuncA();
return 0;
}
3.2.2 桥接模式

场景:当有多个角度变化时, 减少变化带来的膨胀
bridge

对应上图,模式定义中的抽象指的是Shape, 实现指的是Color

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
class Color{
public:
virtual void Fill() = 0;
~Color(){}
};
class Red:public Color{
public:
void Fill()override{printf("red\n");}
};
class Shape{
public:
virtual void Draw() = 0;
void SetColor(Color *color){_color = color;}
~Shape(){}
protected:
Color *_color;
};
class Rect:public Shape{
public:
void Draw()override{printf("Rect with ");_color->Fill();}
};
int main(){
Color *red = new Red;
Shape* rect = new Rect;
rect->SetColor(red);
rect->Draw();
return 0;
}
3.2.3 组合模式

场景:对于组合对象与单个对象使用统一的接口,而忽略它们之间的差异
composite

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
class Entry{
public:
virtual void Add(Entry* e){ throw "Cannot add on leaf node";}
//需要向上遍历可以加个SetParent();
virtual void Operation() = 0;
virtual ~Entry(){}
};
//子类可以随意继承Entry来扩展File类型或Dir 类型
class File:public Entry{
public:
void Operation()override{printf("open file\n");}
};
//留意File的内存释放
class Dir:public Entry{
public:
void Operation()override{
printf("open dir\n");
for(auto& e: _vecChilds){
e->Operation();
}
}
virtual void Add(Entry* e){_vecChilds.push_back(e);}

private:
vector<Entry*> _vecChilds;
};
int main(){
//随意组合
Entry *root = new Dir;
Entry *dir1 = new Dir;
Entry *file1 = new File;
Entry *file2 = new File;
dir1->Add(file1);
root->Add(file2);
root->Add(dir1);

root->Operation();
return 0;
}
3.2.4 装饰模式

场景: 类似于桥接,桥接强调持有,对象本身是多个维度不稳定的,而装饰是一种”套娃”实现, 本身是稳定的, 是为了后续扩展所用
decorator

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
class Shape{
public:
virtual void Draw() = 0;
~Shape(){}
};
class Circle:public Shape{
public:
void Draw()override{printf("Draw Circle\n");}
};
class ShapeDecorator{
public:
virtual void Draw() = 0;
explicit ShapeDecorator(Shape* shape):_shape(shape){}
~ShapeDecorator(){}
//protected:
Shape *_shape;
};
class RedShapeDecorator:public ShapeDecorator{
public:
void Draw()override{printf("select Red\n");_shape->Draw();}
explicit RedShapeDecorator(Shape* shape):ShapeDecorator(shape){}
~RedShapeDecorator(){}
};
int main(){
Shape *shape = new Circle;
ShapeDecorator *redDec = new RedShapeDecorator(shape);
redDec->Draw();
return 0;
}
3.2.5 外观模式

场景: 对外提供统一接口,隐藏复杂实现细节, 类似于系统集成

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
class SubSystem1{
public:
void DoSub1(){}
};
class SubSystem2{
public:
void DoSub2(){}
};
class SubSystem3{
public:
void DoSub3(){}
};

class System{
public:
void Run(){
sub1.DoSub1();
sub2.DoSub2();
sub3.DoSub3();
}
private:
SubSystem1 sub1;
SubSystem1 sub2;
SubSystem1 sub3;
};
int main(){
System sys;
sys.Run();
return 0;
}
3.2.6 享元模式

场景:大量使用对象造成较多的内存开销时, 将共同的部分抽象出来

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 Shape{
public:
virtual void Draw() = 0;
virtual ~Shape(){}
};
class Circle:public Shape{
public:
void Draw()override{printf("Draw");}
};
class ShapeFac{
public:
Shape* GetShape(string key){
auto it = pools.find(key);
if( it == pools.cend())
pools[key] = new Circle;
return pools[key];
}
private:
map<string, Shape*> pools;
};
int main(){
ShapeFac fac;
Shape* shape = fac.GetShape("hello");
shape->Draw();
return 0;
}
3.2.7 代理模式

场景:访问类时需要提供一种控制
proxy

装饰模式重点在于功能扩展,使用时仍需要知道原对象,代理在于功能的控制,不必关心原对象,也就是图依赖箭头的区别

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Subject{
public:
virtual void operation() = 0;
virtual ~Subject(){}
};
class Real:public Subject{
public:
void operation()override{}
};
class Proxy:public Subject{
public:
void operation()override{
//do something
_real.operation();
//do something
}
private:
Real _real;
};
int main(){
Subject *sub = new Proxy;
sub->operation();
return 0;
}

3.3 行为型

3.3.1 责任链模式

场景:多个对象都可能处理一个请求, 可以用职责链来避免if-else耦合调用者和请求

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 Chain{
public:
virtual void Handle() = 0;
void SetNext(Chain* next){_next=next;}
virtual ~Chain(){}
protected:
Chain* _next;
};
class ProcessA:public Chain{
public:
void Handle(){
printf("Handle B\n");
if(_next){
_next->Handle();
}
}
};
class ProcessB:public Chain{
public:
void Handle(){
printf("Handle B\n");
if(_next){
_next->Handle();
}
}
};
int main(){
Chain *pa = new ProcessA;
Chain *pb = new ProcessB;

pa->SetNext(pb);
pa->Handle();
return 0;
}
3.3.2 命令模式

场景:当需要分离接收者和调用者之间的耦合时, 常见比如撤销,重做等
command

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 Reciver{
public:
void Action1(){printf("Action1");}
void Action2(){printf("Action2");}
};

//这里用下纯接口吧(只有纯虚接口)
class ICommond{
public:
virtual void Execute() = 0;
virtual ~ICommond(){}
};

class CommondA:public ICommond{
public:
virtual void Execute(){_rec->Action1();}
explicit CommondA(Reciver *rec):_rec(rec){}
private:
Reciver *_rec;
};

//最简单版
//实现重做/撤销时,可以在命令里边加入redo, undo接口
//invoker负责维护相对应的队列/队列(也就是uml 中画的组合)
class Invoker{
public:
void Invoke(ICommond *cmd){cmd->Execute();}
};

int main(){
Invoker invoker;
Reciver *rec = new Reciver;
ICommond *cmd = new CommondA(rec);
invoker.Invoke(cmd);
return 0;
}
3.3.3 解释器模式

场景:一般特有领域的文法分析才会使用,略

3.3.4 迭代器模式

场景:为遍历不同的聚合结构提供统一的访问方式
iterator

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
class Iterator{
public:
virtual void First() = 0;
virtual void Next() = 0;
virtual bool Done() = 0;
//使用泛型时可用const T&/const T
virtual int Item() = 0;
virtual ~Iterator(){}
};
class Collection{
public:
virtual Iterator* GetIterator() = 0;
virtual void Insert(int val) = 0;
virtual int GetVal(int idx) = 0;
virtual int GetSize() = 0;
virtual ~Collection(){}
};
class IteratorA:public Iterator{
public:
explicit IteratorA(Collection* c):_collection(c),_curIdx(0){}
void First()override{_curIdx = 0;}
void Next()override{_curIdx++;}
bool Done()override{return _curIdx >=_collection->GetSize();}
int Item()override{return _collection->GetVal(_curIdx);}
private:
int _curIdx;
Collection* _collection;

};
class CollectionA:public Collection{
public:
void Insert(int val){_data.push_back(val);}
Iterator* GetIterator()override{return new IteratorA(this);}
int GetVal(int idx)override{return _data[idx];}
int GetSize(){return _data.size();}
private:
vector<int> _data;
};
int main(){
CollectionA c;
c.Insert(1);
c.Insert(2);
c.Insert(3);

auto it = c.GetIterator();
for(it->First(); !it->Done();it->Next()){
printf("%d\n", it->Item());
}

return 0;
}
3.3.5 中介模式

场景:当多个对象之间互相关联时可以通过中介变成多对一,解耦
mediator

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
class Mediator;
class People{
public:
explicit People(Mediator* m):_mediator(m){}
virtual void SendMsg(const string& msg) = 0;
virtual void Update(const string& msg) = 0;
virtual ~People(){}
protected:
Mediator *_mediator;
};
class Mediator{
public:
virtual void Notify(const string& msg, People *p) = 0;
virtual ~Mediator(){}
};
class MediatorA:public Mediator{
public:
void SetPeopleA(People* p){_contactorA = p;}
void SetPeopleB(People* p){_contactorB = p;}
//抽离关联关系,各个对象可以专注自我
void Notify(const string& msg, People *p)override{
if(_contactorA==p)
_contactorB->Update(msg);
else
_contactorA->Update(msg);
}
private:
People* _contactorA;
People* _contactorB;
};
class Boy:public People{
public:
explicit Boy(Mediator* m):People(m){}
void SendMsg(const string& msg)override{_mediator->Notify(msg,this);}
void Update(const string& msg)override{printf("B: %s\n",msg.c_str());}
};
class Girl:public People{
public:
explicit Girl(Mediator* m):People(m){}
void SendMsg(const string& msg)override{_mediator->Notify(msg,this);}
void Update(const string& msg)override{printf("G: %s\n",msg.c_str());}
};
int main(){
MediatorA mediator;
People *tony = new Boy(&mediator);
People *lisa = new Girl(&mediator);
mediator.SetPeopleA(tony);
mediator.SetPeopleB(lisa);

tony->SendMsg("hello");
lisa->SendMsg("hi");

return 0;
}
3.3.6 备忘录模式

场景:对象需要回溯到保存某个版本时
memento

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
class Memento{
public:
int GetStatus()const{return _status;}
void SetStatus(int status){_status = status;}
private:
int _status;
};

class Task{
public:
Memento CreateImg(){
Memento m;
m.SetStatus(_status);
return move(m);
}
void Recovery(Memento* m){
_status = m->GetStatus();
}
int GetStatus(){return _status;}
void SetStatus(int status){_status = status;}
private:
int _status;
};

class CareTaker{
public:
Memento* Undo(){
if(!_mementos.empty()){
auto m = _mementos.top();
_mementos.pop();
return m;
}
}
void Save(Memento* m){_mementos.push(m);}
private:
stack<Memento*> _mementos;
};

int main(){
CareTaker taker;

Task task;
task.SetStatus(0);
printf("%d\n", task.GetStatus());
auto m = task.CreateImg();
taker.Save(&m);

task.SetStatus(1);
printf("%d\n", task.GetStatus());

task.Recovery(taker.Undo());
printf("%d\n", task.GetStatus());
return 0;
}
3.3.7 观察者模式

场景:类似发布订阅, 当需要一对多实时通知时

发布订阅一般第三方例如topic队列来完全解耦,例如Ros系统就是通过注册topic来传递msg,从而联结发布者和订阅者

observer

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 Observer;
class Subject{
public:
virtual void Aattach(Observer*) = 0;
virtual void Dettach(Observer*) = 0;
virtual void Notify() = 0;
int GetStatus() {return _status;}
void SetStatus(int status) {_status = status;}
virtual ~Subject(){};
protected:
set<Observer*> _obs;
int _status;
};

class Observer{
public:
virtual void Update() = 0;
virtual ~Observer(){};
protected:
//如果不需要了解被观察者可以不必
Subject* _sub;
};

class SubjectA: public Subject{
public:
void Aattach(Observer* ob)override {_obs.insert(ob);}
virtual void Dettach(Observer* ob) override{
auto it = _obs.find(ob);
if(it != _obs.end()){
_obs.erase(it);
}
}
virtual void Notify()override{
for(auto& e: _obs){
e->Update();
}
}
};

class ObserverA:public Observer{
public:
ObserverA(Subject* sub){_sub = sub;}
void Update()override{printf("A: %d\n",_sub->GetStatus());}
};

int main(){
Subject* sub = new SubjectA;

Observer* ob = new ObserverA(sub);
Observer* ob2 = new ObserverA(sub);
Observer* ob3 = new ObserverA(sub);

sub->Aattach(ob);
sub->Aattach(ob2);

sub->SetStatus(10);
sub->Notify();
return 0;
}
3.3.8 策略模式

场景:各种算法可以相互替换时(平替if…else)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Strategy{
public:
virtual void Algo() = 0;
virtual ~Strategy(){}
};
class StrategyA:public Strategy{
public:
void Algo()override{printf("Algo A");};
};
class Context{
public:
Context(Strategy *strategy):_strategy(strategy){}
void operation(){_strategy->Algo();}
private:
Strategy *_strategy;
};

int main(){
Strategy *method1 = new StrategyA;
Context ctx(method1);
ctx.operation();
return 0;
}
3.3.9 状态模式

场景:当有多种状态影响对象行为时(平替if…else)

区别于策略模式,状态模式一般需要耦合context来实现状态转移及带来的操作

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
//客户端主动调用Action的方式
class Context;
class Status{
public:
virtual void Action1(Context*) = 0;
virtual void Action2(Context*) = 0;
virtual ~Status(){}
};
class StartStatus:public Status{
public:
void Action1(Context*)override{printf("start Ac1\n");};
void Action2(Context*)override{printf("start Ac2\n");};
};
class StopStatus:public Status{
public:
void Action1(Context*)override{printf("stop Ac1\n");};
void Action2(Context*)override{printf("stop Ac2\n");};
};
class Context{
public:
Context(Status *status):_status(status){}
void Action1(){_status->Action1(this);}
void Action2(){_status->Action2(this);}
void SetStatus(Status *status){_status = status;}
/*也可以这样来自动action,通常也是这种方式
void ChangeStatus(Status* status){
//action 中设置context 状态
status->Action(this);
}
客户端:ctx.ChangeStatus(stopStatus);
有限状态就可以基于这种形式加上nextStatus 的指针
*/
private:
Status *_status;
};

int main(){
//主动形式与策略基本没什么区别,不过策略一般上下文不会变动
Status *start = new StartStatus;
Status *stop = new StopStatus;
Context ctx(start);
ctx.Action1();
ctx.SetStatus(stop);
ctx.Action1();
return 0;
}
3.3.10 模板模式

场景:有共同的步骤代码,将不确定的部分延迟

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 Template{
public:
void method(){
//do something
stepA();
//do something
stepB();
stepC();
}
virtual ~Template(){}
protected:
virtual void stepA() = 0;
virtual void stepB() = 0;
virtual void stepC() = 0;
};
class Imp1: public Template{
protected:
void stepA()override{}
void stepB()override{}
void stepC()override{}
};
int main(){
Template* tmp = new Imp1;
tmp->method();
return 0;
}
3.3.11 访问者模式

visitor
场景: 总体结构稳定但对部件算法不稳定的时候可以将结构和操作分离开来,一般比较少使用

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
//注意声明的顺序, 这个模式是循环依赖的
//visitor, 对不同的结构生成不同的操作
class Visitor{
public:
virtual void visit(PartA*) = 0;
virtual void visit(PartB*) = 0;
~Visitor(){}
};

class PartA;
class PartB;

class Partail{
public:
virtual void Accept(Visitor* visitor) = 0;
virtual ~Partail(){}
};

class PartA:public Partail{
public:
void Accept(Visitor* visitor)override{visitor->visit(this);}
string GetName(){return "PartA";}
};
class PartB:public Partail{
public:
void Accept(Visitor* visitor)override{visitor->visit(this);}
string GetName(){return "PartB";}
};
class Whole{
public:
void Show(Visitor* visitor){
a.Accept(visitor);
b.Accept(visitor);
}
private:
PartA a;
PartB b;
};

class Visitor1:public Visitor{
public:
void visit(PartA* a)override{printf("visit1 %s\n", a->GetName().c_str());}
void visit(PartB* b)override{printf("visit1 %s\n",b->GetName().c_str());}
};
int main(){
Visitor* visitor = new Visitor1;
Whole whole;
whole.Show(visitor);
return 0;
}

参考文献:
1.https://www.cnblogs.com/call-me-pengye/p/12201675.html
2.https://www.runoob.com/design-pattern/design-pattern-tutorial.html
3.https://zhuanlan.zhihu.com/p/83535678
4.https://zhuanlan.zhihu.com/p/365222623