【设计模式】行为型模式

行为型模式

学习笔记之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;
}


输出:

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

命令模式中的角色和职责


策略模式


观察者模式



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