前言

备忘录、迭代器和解释器模式(行为型设计模式)的 C++ 代码示例模板。


代码仓库


备忘录模式(Memento)

结构

  • 备忘录类(保存 发起者对象 的状态)
  • 发起者类(需要保存和恢复状态 的对象)
  • 管理者类(管理备忘录对象)
  • 备忘录类 封装 状态属性,保存状态方法,获取状态方法
  • 发起者类 封装 状态属性,设置状态方法,创建备忘录(保存状态)方法(将状态交给备忘录保存),恢复备忘录(恢复状态)方法(从备忘录获取/恢复状态)
  • 管理者类 封装 添加备忘录方法,获取备忘录方法
  • 备忘录过程:发起者 调用 创建备忘录(保存状态)方法 -> 管理者 调用 添加备忘录方法;管理者 调用 获取备忘录方法 -> 发起者 调用 恢复备忘录(恢复状态)方法
  • 基于嵌套类的实现中,备忘录类 是 发起者类 的内部类,发起者类 管理 备忘录类 的创建和恢复,通常不需要管理者类

类型:

  • 基于非嵌套类/接口的实现:支持和不支持嵌套类的编程语言(如 PHP) 可以实现
  • 基于嵌套类的实现:只能在 支持嵌套类的编程语言(如 C++、 C# 和 Java) 实现

代码(基于非嵌套类/接口的实现)

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
#include <string>
#include <iostream>
#include <vector>

using std::cout;
using std::endl;
using std::string;
using std::vector;

// 备忘录类(保存 发起者对象 的状态)
// 备忘录类 封装 状态属性,保存状态方法,获取状态方法
class Memento
{
public:
Memento(string state) : state(state) {} // 保存状态

// 设置状态

// 获取状态
string get_state()
{
return this->state;
}

private:
string state; // 状态
};

// 发起者类(需要保存和恢复状态 的对象)
// 发起者类 封装 状态属性,设置状态方法,创建备忘录(保存状态)方法(将状态交给备忘录保存),恢复备忘录(恢复状态)方法(从备忘录获取/恢复状态)
class Initiator
{
public:
// 设置状态
void set_state(string state)
{
this->state = state;
cout << "Current state: " << this->state << endl;
}

// 获取状态

// 创建备忘录(保存状态)
Memento create_memento()
{
return Memento(this->state); // 将状态交给备忘录保存
}

// 恢复备忘录(恢复状态)
void restore_memento(Memento memento)
{
this->state = memento.get_state(); // 从备忘录获取/恢复状态
cout << "State restores to: " << this->state << endl;
}

private:
string state; // 状态
};

// 管理者类(管理备忘录对象)
// 管理者类 封装 添加备忘录方法,获取备忘录方法
class Administrator
{
public:
// 添加备忘录
void add_memento(Memento memento)
{
this->memento_vec.push_back(memento);
}

// 获取备忘录
const Memento get_memento(int index)
{
return this->memento_vec.at(index);
}

private:
vector<Memento> memento_vec;
};

// 客户端
int main()
{
// 发起者对象
Initiator initiator;
// 管理者对象
Administrator administrator;

initiator.set_state("State 1"); // 设置状态
// 备忘录对象
Memento memento_1 = initiator.create_memento(); // 1. 创建备忘录(保存状态)
administrator.add_memento(memento_1); // 2. 添加备忘录

initiator.set_state("State 2"); // 设置状态
Memento memento_2 = administrator.get_memento(0); // 3. 获取备忘录
initiator.restore_memento(memento_2); // 4. 恢复备忘录(恢复状态)
// 备忘录过程:
// 发起者 调用 创建备忘录(保存状态)方法 -> 管理者 调用 添加备忘录方法
// 管理者 调用 获取备忘录方法 -> 发起者 调用 恢复备忘录(恢复状态)方法

return 0;
}
/*
输出:
Current state: State 1
Current state: State 2
State restores to: State 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
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
#include <string>
#include <iostream>
#include <vector>

using std::cout;
using std::endl;
using std::string;
using std::vector;

// 发起者类(需要保存和恢复状态 的对象)
// 发起者类 封装 状态属性,设置状态方法,创建备忘录(保存状态)方法(将状态交给备忘录保存),恢复备忘录(恢复状态)方法(从备忘录获取/恢复状态)
class Initiator
{
public:
// 备忘录类(保存 发起者对象 的状态)
// 备忘录类 封装 状态属性,保存状态方法,获取状态方法
class Memento
{
public:
Memento(string state) : state(state) {} // 保存状态

// 设置状态

// 获取状态
string get_state()
{
return this->state;
}

private:
string state; // 状态
};

public:
// 设置状态
void set_state(string state)
{
this->state = state;
cout << "Current state: " << this->state << endl;
}

// 获取状态

// 创建备忘录(保存状态)
Memento create_memento()
{
return Memento(this->state); // 将状态交给备忘录保存
}

// 恢复备忘录(恢复状态)
void restore_memento(Memento memento)
{
this->state = memento.get_state(); // 从备忘录获取/恢复状态
cout << "State restores to: " << this->state << endl;
}

private:
string state; // 状态
};

// 基于嵌套类的实现中,备忘录类 是 发起者类 的内部类,发起者类 管理 备忘录类 的创建和恢复,通常不需要管理者类

// 客户端
int main()
{
// 发起者对象
Initiator initiator;

initiator.set_state("State 1"); // 设置状态
// 备忘录对象
Initiator::Memento memento_1 = initiator.create_memento(); // 1. 创建备忘录(保存状态)

initiator.set_state("State 2"); // 设置状态
initiator.restore_memento(memento_1); // 2. 恢复备忘录(恢复状态)

return 0;
}
/*
输出:
Current state: State 1
Current state: State 2
State restores to: State 1
*/

迭代器模式(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
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
#include <string>
#include <vector>
#include <iostream>

using std::cout;
using std::endl;
using std::string;
using std::vector;

// 项目类(需要迭代 的对象)
class Item
{
public:
Item(string name) : name(name) {}

// 获取名称
string get_name()
{
return this->name;
}

private:
string name; // 名称
};

// 抽象迭代器类
class AbstractIterator
{
public:
virtual Item *get_first() = 0; // 获取第一个项目
virtual Item *get_next() = 0; // 获取下一个项目
};

// 具体迭代器类(帮助迭代 的对象)
class ConcreteIterator : public AbstractIterator
{
public:
ConcreteIterator(vector<Item *> item_vec) : item_vec(item_vec), cur_index(0) {}

// 获取第一个项目
Item *get_first() override
{
Item *item = this->item_vec[0];

if (item != nullptr) // 有第一个项目
{
return item; // 返回第一个项目
}
else // 无第一个项目
{
return nullptr; // 返回空指针
}
}

// 获取下一个项目
Item *get_next() override
{
if ((this->cur_index < (this->item_vec.size() - 1)) == true)
// 索引 = 大小 - 1
// 如果 项目的当前索引 小于 项目集合的大小 - 1,返回 true,有下一个项目
// 如果 项目的当前索引 等于或大于 项目集合的大小 - 1,返回 false,无下一个项目
{
++this->cur_index;
Item *item = this->item_vec[this->cur_index];

return item;
}
else
{
return nullptr;
}
}

private:
vector<Item *> item_vec; // 项目指针(实际上指向一个项目对象)的集合
size_t cur_index; // 项目集合的当前索引
};

// 抽象聚合类
class AbstractAggregate
{
public:
virtual AbstractIterator *create_iterator() = 0; // 创建迭代器
};

// 具体聚合类(连接 项目集合 和 迭代器,获取 并 使用 项目集合 创建 迭代器)
class ConcreteAggregate : public AbstractAggregate
{
public:
ConcreteAggregate(vector<Item *> item_vec) : item_vec(item_vec) {}

// 创建迭代器(抽象迭代器指针类型 的 具体迭代器指针)
AbstractIterator *create_iterator() override
{
return new ConcreteIterator(this->item_vec);
}

private:
vector<Item *> item_vec;
};

// 客户端
int main()
{
// 项目对象的集合
Item *item_1 = new Item("Item1");
Item *item_2 = new Item("Item2");
Item *item_3 = new Item("Item3");
vector<Item *> item_vec = {item_1, item_2, item_3};

// 具体聚合对象
ConcreteAggregate aggregate(item_vec);

// 抽象迭代器指针类型 的 具体迭代器指针
AbstractIterator *iterator = aggregate.create_iterator(); // 创建迭代器

// 使用 具体迭代器指针 遍历 项目对象的集合
for (Item *item = iterator->get_first(); item != nullptr; item = iterator->get_next())
{
cout << "Item: " << item->get_name() << endl;
}

delete iterator;
for (Item *item : item_vec)
{
delete item;
}

return 0;
}
/*
输出:
Item: Item1
Item: Item2
Item: Item3
*/

解释器模式(Interpreter)

结构

  • 抽象表达式类
  • 终结符表达式类 (树叶结点;用于将 变量 解释为 值)
  • 非终结符表达式类 (树枝结点;用于将 表达式 解释为 操作)
  • 上下文类(用于 设置 变量和值的映射 和 获取 变量 映射的 值)
  • 抽象表达式类 封装 解释方法
  • 终结符表达式类 封装 变量 和 重写 解释方法
  • 非终结符表达式类 封装 抽象表达式指针(实际上指向一个 终结符表达式对象 或 非终结符表达式对象) 和 重写 解释方法(形式上 调用 非终结符表达式类的 解释方法, 实际上 调用 终结符表达式类 或 非终结符表达式类的 解释方法(递归))
  • 上下文类 封装 上下文/变量和值的映射属性、设置 变量和值的映射方法 和 获取 变量 映射的 值方法
  • 创建过程:反向创建:先创建树叶,后创建树枝
  • 解释过程:正向解释:先解释树枝,后解释树叶(树状递归)

代码

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
#include <unordered_map>
#include <iostream>

using std::cout;
using std::endl;
using std::unordered_map;

// 抽象表达式类
class AbstractExpression
{
public:
// 解释
virtual int interpret(unordered_map<char, int> context_unmap) = 0;
};

// 终结符表达式类(树叶结点;用于将 变量 解释为 值)
class TerminalExpression : public AbstractExpression
{
public:
TerminalExpression(char var) : var(var) {}

// 解释
int interpret(unordered_map<char, int> context_unmap) override
{
return context_unmap[this->var];
}

private:
// 变量
char var;
};

// 非终结符表达式类(树枝结点;用于将 表达式 解释为 操作)
class NonTerminalExpression : public AbstractExpression
{
public:
NonTerminalExpression(AbstractExpression *expr_1, AbstractExpression *expr_2) : expr_1(expr_1), expr_2(expr_2) {}

// 解释
int interpret(unordered_map<char, int> context_unmap) override // 形式上 调用 非终结符表达式类的 解释方法
{
// 这里 解释为 加法操作
return expr_1->interpret(context_unmap) + expr_2->interpret(context_unmap); // 实际上 调用 终结符表达式类 或 非终结符表达式类的 解释方法(递归)
}

private:
// 抽象表达式指针(实际上指向一个 终结符表达式对象 或 非终结符表达式对象)
AbstractExpression *expr_1;
AbstractExpression *expr_2;
};

// 上下文类(用于 设置和获取 变量和值的映射)
class Context
{
public:
Context() : context_unmap() {} // unordered_map<> 的默认构造方法 初始化

// 设置 变量和值的映射
void set_var_value(char var, int value)
{
this->context_unmap[var] = value;
}

// 获取 变量和值的映射
unordered_map<char, int> get_var_value()
{
return this->context_unmap;
}

private:
// 上下文/变量和值的映射
unordered_map<char, int> context_unmap;
};

// 客户端
int main()
{
// 构建表达式:a + b
AbstractExpression *expr_1 = new TerminalExpression('a'); // 抽象表达式指针(实际上指向一个终结符表达式对象)
AbstractExpression *expr_2 = new TerminalExpression('b');
AbstractExpression *expr_3 = new NonTerminalExpression(expr_1, expr_2); // 抽象表达式指针(实际上指向一个非终结符表达式对象)

Context context; // 上下文对象
// 设置 变量和值的映射
context.set_var_value('a', 10);
context.set_var_value('b', 20);

// 获取 变量和值的映射
unordered_map<char, int> context_unmap = context.get_var_value();

// 解释
int result = expr_3->interpret(context_unmap);
cout << "Result: " << result << endl;
// 创建过程:
// 反向创建:先创建树叶,后创建树枝
// 解释过程:
// 正向解释:先解释树枝,后解释树叶(树状递归)

delete expr_3;
delete expr_2;
delete expr_1;

return 0;
}
/*
输出:
Result: 30
*/

总结

备忘录、迭代器和解释器模式(行为型设计模式)的 C++ 代码示例模板。


参考资料


作者的话

  • 感谢参考资料的作者/博主
  • 作者:夜悊
  • 版权所有,转载请注明出处,谢谢~
  • 如果文章对你有帮助,请点个赞或加个粉丝吧,你的支持就是作者的动力~
  • 文章在描述时有疑惑的地方,请留言,定会一一耐心讨论、解答
  • 文章在认识上有错误的地方, 敬请批评指正
  • 望读者们都能有所收获