【设计模式】行为型模式

文章目录
  1. 1. 行为型模式
  2. 2. 模板方法模式
    1. 2.1. 模板方法案例
    2. 2.2. 代码
    3. 2.3. 适用场景
  3. 3. 命令模式
    1. 3.1. 代码
    2. 3.2. 命令模式中的角色和职责
  4. 4. 策略模式
  5. 5. 观察者模式

行为型模式

学习笔记之C++设计模式——创建型模式

📑 【设计模式】结构型模式

📑 【设计模式】创建型模式

总的来说,行为型模式就是用来对类或对象怎样交互和怎样分配职责进行描述。

模板方法模式

模板方法

AbstractClass(抽象类):在抽象类中定义了一系列基本操作(PrimitiveOperations),这些基本操作可以是具体的,也可以是抽象的,每一个基本操作对应算法的一个步骤,在其子类中可以重定义或实现这些步骤。同时,在抽象类中实现了一个模板方法(Template Method),用于定义一个算法的框架,模板方法不仅可以调用在抽象类中实现的基本方法,也可以调用在抽象类的子类中实现的基本方法,还可以调用其他对象中的方法。

ConcreteClass(具体子类):它是抽象类的子类,用于是现在父类中声明的抽象基本操作以完成子类特定算法的步骤,也可以覆盖在父类中的已经实现的具体基本操作。

模板方法案例

模板方法案例

代码

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
// 模板方法.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;

// 制作饮料
class Beverage
{
public:
// 煮水
void BoilWater() {
cout << "烧开水" << endl;
}
// 冲泡 特殊接口
virtual void Brew() = 0;
// 倒入杯中
void PourinVup() {
cout << "倒入杯中" << endl;
}
// 添加料 特殊接口
virtual void AddCondiments() = 0;

// hook 方法,决定某些算法步骤是否挂钩在算法中
virtual bool CustomWantsCondiments() {
return true;
}

// 模板方法
void PrepareBeverage() {
BoilWater();
Brew();
PourinVup();
if (CustomWantsCondiments()) {
AddCondiments();
}
}
protected:

private:
};

class Coffee : public Beverage
{
public:
virtual void Brew() {
cout << "冲泡咖啡豆" << endl;
}
virtual void AddCondiments() {
cout << "添加糖和牛奶" << endl;
}
protected:
private:
};


class Tea : public Beverage
{
public:
virtual void Brew() {
cout << "冲泡茶叶" << endl;
}
virtual void AddCondiments() {
cout << "添加柠檬" << endl;
}
protected:
private:
};

int main()
{
Beverage *pTea = new Tea;
pTea->PrepareBeverage();
delete pTea;

cout << "-----------------------" << endl;

Beverage *pCoffee = new Tea;
pCoffee->PrepareBeverage();
delete pCoffee;

return 0;
}

输出:

烧开水
冲泡茶叶
倒入杯中
添加柠檬
-----------------------
烧开水
冲泡茶叶
倒入杯中
添加柠檬
请按任意键继续. . .
## 模板方法的优缺点
  1. 在父类中形式化地定义一个算法,而由它的子类来实现细节的处理,在子类实现详细的处理算法时并不会改变算法中步骤的执行次序。
  2. 模板方法模式是一种代码复用技术,它在类库设计中尤为重要,它提取了类库中的公共行为,将公共行为放在父类中,而通过其子类来实现不同的行为,它鼓励我们恰当使用继承来实现代码复用。
  3. 可实现一种反向控制结构,通过子类覆盖父类的钩子方法来决定某一特定步骤是否需要执行。
  4. 在模板方法模式中可以通过子类来覆盖父类的基本方法,不同的子类可以提供基本方法的不同实现,更换和增加新的子类很方便,符合单一职责原则和开闭原则

需要为每一个基本方法的不同实现提供一个子类,如果父类中可变的基本方法太多,将会导致类的个数增加,系统更加庞大,设计也更加抽象。

适用场景

  1. 具有统一的操作步骤或操作过程;

  2. 具有不同的操作细节;

  3. 存在多个具有同样操作步骤的应用场景,但某些具体的操作细节却各不相同

在抽象类中统一操作步骤,并规定好接口;让子类实现接口。这样可以吧各个具体的子类和操作步骤解耦合。


命令模式

将一个请求封装为一个对象,从而让我们可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。命令模式是一种对象行为模式,其别名为动作(Action)模式或事务(Tranaction)模式。

命令模式可以将请求发送者和接收者完全解耦,发送者与接收者之间没有直接引用关系,发送请求的对象只需要知道如何发送请求,而不必知道如何完成请求。

代码

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
// 命令模式.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
using namespace std;

class Doctor
{
public:
void treat_eye() {
cout << "医生 治疗 眼科病" << endl;
}
void treat_nose() {
cout << "医生 治疗 鼻科病" << endl;
}
protected:
private:
};

class CommandTreatEye {
public:
CommandTreatEye(Doctor *doctor) {
m_doctor = doctor;
}

void treat() {
m_doctor->treat_eye();
}
private:
Doctor *m_doctor;
};

class CommandTreatNose {
public:
CommandTreatNose(Doctor *doctor) {
m_doctor = doctor;
}

void treat() {
m_doctor->treat_nose();
}
private:
Doctor *m_doctor;
};

int main()
{
// 1. 医生直接看病
Doctor *doctor = new Doctor;
doctor->treat_eye();

delete doctor;

cout << "-----------------" << endl;

// 2. 通过医疗指令来看病

Doctor *doctorCmd = new Doctor;
CommandTreatEye * cmdEyeDoc = new CommandTreatEye(doctorCmd);
cmdEyeDoc->treat();
delete cmdEyeDoc;

CommandTreatNose *cmdNoseDoc = new CommandTreatNose(doctorCmd);
cmdNoseDoc->treat();
delete cmdNoseDoc;

delete doctorCmd;

return 0;
}


输出:

医生 治疗 眼科病
-----------------
医生 治疗 眼科病
医生 治疗 鼻科病
请按任意键继续. . .
> 命令模式的本质是对请求进行封装对应于一个命令,将发出命令的责任和执行命令的责任分割开。

命令模式中的角色和职责


策略模式


观察者模式