Chain of Responsibility (责任链)

责任链模式是一种行为设计模式,将请求沿着处理者链进行发送。在收到请求后,每个处理者均可选择对请求进行处理, 或将其继续传递给下个处理者。

首先我们需要创建一个抽象处理者基类HandlerBase,对外提供了几个方法:

  • set_next:与另一个处理者建立后继关系,当前处理者可能把请求处理完成,也可能将请求传递给后继者;
  • handle_request:尝试处理请求,为了避免在责任链中出现死循环,使用哈希表记录下曾经出现过的处理者,处理过程有三种结果:
    • 遇到了可以处理请求的对象,处理成功;
    • 回到之前遇到的处理者,表明出现死循环,处理失败;
    • 责任链查找到了尽头,即不存在后继者,处理失败。

HandlerBase还预留了几个接口:

  • can_handle:判断是否可以处理完成当前的请求,返回布尔值
  • handle:处理当前的请求

从基类HandlerBase继承得到各种类型的具体处理者(例如HandlerAHandlerBHandlerC), 它们分别实现了不同版本的can_handlehandle,不同类型的处理者可以相互连接以组成责任链。

示例代码如下

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

// 抽象处理者基类
class HandlerBase {
public:
virtual ~HandlerBase() = default;

void set_next(std::shared_ptr<HandlerBase> nextHandler) {
m_next = nextHandler;
}

void handle_request(const std::string &request) {
std::unordered_set<HandlerBase *> visitedHandlers;
handle_request_internal(request, visitedHandlers);
}

protected:
virtual bool can_handle(const std::string &request) = 0;
virtual void handle(const std::string &request) = 0;

private:
std::shared_ptr<HandlerBase> m_next = nullptr;

void handle_request_internal(
const std::string &request,
std::unordered_set<HandlerBase *> &visitedHandlers) {
if (visitedHandlers.find(this) != visitedHandlers.end()) {
std::cout << "Circular reference detected. Aborting." << std::endl;
return;
}

visitedHandlers.insert(this);

if (can_handle(request)) { handle(request); }
else if (m_next) {
m_next->handle_request_internal(request, visitedHandlers);
}
else {
std::cout << "No handler for request: " << request << std::endl;
}
}
};

// 具体处理者A
class HandlerA : public HandlerBase {
protected:
bool can_handle(const std::string &request) override {
return request == "Request type A";
}

void handle(const std::string &request) override {
std::cout << "HandlerA handling: " << request << std::endl;
}
};

// 具体处理者B
class HandlerB : public HandlerBase {
protected:
bool can_handle(const std::string &request) override {
return request == "Request type B";
}

void handle(const std::string &request) override {
std::cout << "HandlerB handling: " << request << std::endl;
}
};

// 具体处理者C
class HandlerC : public HandlerBase {
protected:
bool can_handle(const std::string &request) override {
return request == "Request type C";
}

void handle(const std::string &request) override {
std::cout << "HandlerC handling: " << request << std::endl;
}
};

int main() {
auto handler1 = std::make_shared<HandlerA>();
auto handler2 = std::make_shared<HandlerB>();
auto handler3 = std::make_shared<HandlerC>();

handler1->set_next(handler2);
handler2->set_next(handler3);

handler1->handle_request("Request type A");
handler1->handle_request("Request type B");
handler1->handle_request("Request type C");
handler1->handle_request("Request type D");

return 0;
}

运行结果如下

1
2
3
4
HandlerA handling: Request type A
HandlerB handling: Request type B
HandlerC handling: Request type C
No handler for request: Request type D

责任链模式通常可以与组合模式结合,在组合模式中我们已经在对象之间建立了树结构,这非常利于实现责任链,请求可以很自然地从叶子节点向根节点方向传递。

对于责任链模式的应用,通常可以分为如下两种情景:

  • 第一种情况是希望请求被尽早处理,例如GUI界面上的操作通常会先检查最小的组件能否处理完成,如果可以就直接处理请求,否则查找它的上一级组件,直到最上层的对象;
  • 第二种情况是希望请求被传递给责任链的终点,例如对请求进行合法性检查,除了终点之外的每一个处理者都是检查者,分别负责一个方面的检查,如果请求不满足要求则将其丢弃,只有满足所有检查的请求才会被传递给真正的处理者。

Command (命令)

命令模式是一种行为设计模式,它可将请求转换为一个包含与请求相关的所有信息的独立对象。 转换方法能根据不同的请求将方法参数化、延迟请求执行或将其放入队列中,且能实现可撤销操作。

由于不允许使用函数作为一等公民,在面向对象语言中必须将函数包装为一个具有execute方法的命令对象,这样就得到了命令模式,实现过程如下:

  • 第一步,定义抽象的命令基类Command,预留名为execute的执行接口;
  • 第二步,定义命令的作用对象类型——接收者类Light
  • 第三步,定义具体的命令类型(LightOnCommandLightOffCommand),它需要实现execute方法,并且还需要在对象内部存储接收者指针;
  • 第四步,定义命令的调用对象类型RemoteControl,它在内部存储若干个命令对象指针,在执行命令时调用对应的execute方法。

示例代码如下

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

// 命令接口
class Command {
public:
virtual ~Command() = default;
virtual void execute() = 0;
};

// 接收者类
class Light {
public:
void on() { std::cout << "Light is ON" << std::endl; }

void off() { std::cout << "Light is OFF" << std::endl; }
};

// 具体命令类 - 打开灯
class LightOnCommand : public Command {
private:
Light *m_light;

public:
explicit LightOnCommand(Light *l) : m_light(l) {}

void execute() override { m_light->on(); }
};

// 具体命令类 - 关灯
class LightOffCommand : public Command {
private:
Light *m_light;

public:
explicit LightOffCommand(Light *l) : m_light(l) {}

void execute() override { m_light->off(); }
};

// 调用者类
class RemoteControl {
private:
std::vector<std::shared_ptr<Command>> m_onCommands;
std::vector<std::shared_ptr<Command>> m_offCommands;

public:
explicit RemoteControl(size_t n) : m_onCommands(n), m_offCommands(n) {}

void setCommand(int slot, std::shared_ptr<Command> onCommand,
std::shared_ptr<Command> offCommand) {
m_onCommands[slot] = std::move(onCommand);
m_offCommands[slot] = std::move(offCommand);
}

void pressOnButton(int slot) {
if (m_onCommands[slot]) { m_onCommands[slot]->execute(); }
}

void pressOffButton(int slot) {
if (m_offCommands[slot]) { m_offCommands[slot]->execute(); }
}
};

int main() {
Light livingRoomLight;
Light kitchenLight;

RemoteControl remote(2);
remote.setCommand(0, std::make_shared<LightOnCommand>(&livingRoomLight),
std::make_shared<LightOffCommand>(&livingRoomLight));
remote.setCommand(1, std::make_shared<LightOnCommand>(&kitchenLight),
std::make_shared<LightOffCommand>(&kitchenLight));

remote.pressOnButton(0);
remote.pressOffButton(0);
remote.pressOnButton(1);
remote.pressOffButton(1);

return 0;
}

运行结果如下

1
2
3
4
Light is ON
Light is OFF
Light is ON
Light is OFF

Iterator (迭代器)

迭代器模式是一种行为设计模式,可以在不暴露集合底层表现形式(列表、 栈和树等)的情况下对外提供遍历所有元素的方式。

迭代器的实现比较简单直观:

  • 第一步,定义迭代器基类Iterator,提供hasNextnext两个接口,用于判断是否遍历结束,以及遍历下一个元素。
  • 第二步,定义对数组的迭代器类ArrayIterator,它的构造需要提供数组的原始指针,以及数组长度,在内部需要记录一下当前位置,它需要实现next()方法,返回当前位置的元素副本,与此同时,当前位置自动后移,还需要实现hasNext方法判断是否越界。
  • 第三步,定义集合基类Collection,提供添加元素的接口add和创建迭代器的接口createIterator,后者应该返回一个可以遍历当前集合的迭代器对象。
  • 第四步,定义具体的数组集合类ArrayCollection,负责继承并实现集合基类Collection的两个接口。

示例代码如下,这里对集合中的数据类型使用了模板参数T

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

// 迭代器接口
template <typename T>
class Iterator {
public:
virtual bool hasNext() = 0;
virtual T next() = 0;
virtual ~Iterator() = default;
};

// 具体迭代器类
template <typename T>
class ArrayIterator : public Iterator<T> {
public:
ArrayIterator(T *array, int size) : m_array(array), m_size(size) {}

bool hasNext() override { return m_index < m_size; }

T next() override { return m_array[m_index++]; }

private:
T *m_array;
int m_size;
int m_index = 0;
};

// 集合接口
template <typename T>
class Collection {
public:
virtual void add(const T &element) = 0;
virtual std::unique_ptr<Iterator<T>> createIterator() const = 0;
virtual ~Collection() = default;
};

// 具体集合类
template <typename T>
class ArrayCollection : public Collection<T> {
public:
explicit ArrayCollection(int capacity) : m_capacity(capacity) {
m_array = new T[m_capacity];
}

~ArrayCollection() override { delete[] m_array; }

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

void add(const T &element) override {
if (m_size < m_capacity) { m_array[m_size++] = element; }
else { std::cerr << "Array is full. Cannot add more elements.\n"; }
}

std::unique_ptr<Iterator<T>> createIterator() const override {
return std::make_unique<ArrayIterator<T>>(m_array, m_size);
}

private:
T *m_array;
int m_capacity;
int m_size = 0;
};

int main() {
ArrayCollection<int> collection(10);
collection.add(1);
collection.add(2);
collection.add(3);
collection.add(4);

auto it = collection.createIterator();
while (it->hasNext()) {
std::cout << it->next() << " ";
}
std::cout << std::endl;

return 0;
}

运行结果如下

1
1 2 3 4

在C++的STL中大量地使用了迭代器模式,STL中的算法对容器的访问几乎都是通过迭代器实现的, 并且STL实际上提供了很多种不同的迭代器,可以有很多种分类:

  • 只读/只写/读写
  • 正向/反向/双向/随机
  • ...

关于STL中的迭代器,这里不做过多讨论。

Mediator (中介者)

中介者模式是一种行为设计模式,可以减少对象之间混乱无序的依赖关系。该模式会限制对象之间的直接交互,迫使它们通过一个中介者对象进行合作,从网状、无中心的直接交互变成了中心化的间接交互。

中介者的实现比较复杂,C++需要进行类型前置声明等合规性处理:

  • 第一步,我们需要对同事类基类ColleagueBase进行前置声明;
  • 第二步,定义中介者基类MediatorBase,它预留了两个接口:
    • addColleague:添加一个同事类对象指针
    • send_by_mediator:在同事之间进行一对多的消息传递
  • 第三步,定义同事类基类ColleagueBase, 它的构造需要传入一个中介者基类指针和自身的唯一标识符id,提供如下接口:
    • send:向其它同事发送消息
    • receive:从其它同事接收消息
  • 第四步,定义具体的同事类(ColleagueAColleagueBColleagueC),具体实现基类的对应接口
  • 第五步,定义具体的中介者类Mediator,它在内部使用字典记录当前注册的所有同事类对象指针,使用它们的id作为字典索引,具体实现基类的相应接口。

示例代码如下

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
137
138
139
140
141
142
#include <iostream>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

// 前置声明
class ColleagueBase;

// 中介者基类
class MediatorBase {
public:
virtual ~MediatorBase() = default;
virtual void
send_by_mediator(ColleagueBase *sender, const std::string &message,
const std::vector<std::string> &receiverIds) = 0;
virtual void addColleague(ColleagueBase *colleague) = 0;
};

// 同事类基类
class ColleagueBase {
protected:
MediatorBase *mediator;
std::string id;

public:
ColleagueBase(MediatorBase *m, std::string id)
: mediator(m), id(std::move(id)) {}

virtual void send(const std::string &message,
const std::vector<std::string> &receiverIds) = 0;
virtual void receive(const std::string &message) = 0;
virtual ~ColleagueBase() = default;

std::string getId() const { return id; }
};

// 具体的同事类 A
class ColleagueA : public ColleagueBase {
public:
ColleagueA(MediatorBase *m, const std::string &id) : ColleagueBase(m, id) {}

void send(const std::string &message,
const std::vector<std::string> &receiverIds) override {
std::cout << "[" << id << "] sends: \"" << message << "\" to {";
for (const auto &receiverId : receiverIds) {
std::cout << receiverId << ",";
}
std::cout << "}" << std::endl;
mediator->send_by_mediator(this, message, receiverIds);
}

void receive(const std::string &message) override {
std::cout << "[" << id << "] receives: \"" << message << "\""
<< std::endl;
}
};

// 具体的同事类 B
class ColleagueB : public ColleagueBase {
public:
ColleagueB(MediatorBase *m, const std::string &id) : ColleagueBase(m, id) {}

void send(const std::string &message,
const std::vector<std::string> &receiverIds) override {
std::cout << "[" << id << "] sends: \"" << message << "\" to {";
for (const auto &receiverId : receiverIds) {
std::cout << receiverId << ",";
}
std::cout << "}" << std::endl;
mediator->send_by_mediator(this, message, receiverIds);
}

void receive(const std::string &message) override {
std::cout << "[" << id << "] receives: \"" << message << "\""
<< std::endl;
}
};

// 具体的同事类 C
class ColleagueC : public ColleagueBase {
public:
ColleagueC(MediatorBase *m, const std::string &id) : ColleagueBase(m, id) {}

void send(const std::string &message,
const std::vector<std::string> &receiverIds) override {
std::cout << "[" << id << "] sends: \"" << message << "\" to {";
for (const auto &receiverId : receiverIds) {
std::cout << receiverId << ",";
}
std::cout << "}" << std::endl;
mediator->send_by_mediator(this, message, receiverIds);
}

void receive(const std::string &message) override {
std::cout << "[" << id << "] receives: \"" << message << "\""
<< std::endl;
}
};

// 具体的中介者类
class Mediator : public MediatorBase {
private:
std::unordered_map<std::string, ColleagueBase *> m_colleagues;

public:
void addColleague(ColleagueBase *colleague) override {
std::string id = colleague->getId();
m_colleagues[id] = colleague;
}

void
send_by_mediator(ColleagueBase *sender, const std::string &message,
const std::vector<std::string> &receiverIds) override {
for (const auto &receiverId : receiverIds) {
auto it = m_colleagues.find(receiverId);
if (it != m_colleagues.end()) { it->second->receive(message); }
else {
std::cout << "Receiver with ID " << receiverId << " not found!"
<< std::endl;
}
}
}
};

int main() {
Mediator mediator;

ColleagueA colleagueA(&mediator, "A");
ColleagueB colleagueB(&mediator, "B");
ColleagueC colleagueC(&mediator, "C");

mediator.addColleague(&colleagueA);
mediator.addColleague(&colleagueB);
mediator.addColleague(&colleagueC);

colleagueA.send("Hello, B and C!", {"B", "C"});
colleagueB.send("Hi, A and C!", {"A", "C"});
colleagueC.send("Hey, A!", {"A"});

return 0;
}

运行结果如下

1
2
3
4
5
6
7
8
[A] sends: "Hello, B and C!" to {B,C,}
[B] receives: "Hello, B and C!"
[C] receives: "Hello, B and C!"
[B] sends: "Hi, A and C!" to {A,C,}
[A] receives: "Hi, A and C!"
[C] receives: "Hi, A and C!"
[C] sends: "Hey, A!" to {A,}
[A] receives: "Hey, A!"

Memento (备忘录)

备忘录模式是一种行为设计模式,允许在不暴露对象实现细节的情况下保存和恢复对象之前的状态(快照)。

备忘录模式的目的就是创建备份,为了避免暴露对象内部细节, 我们需要提供一个通用的数据类型——备忘录类Memento,备忘录的内部以某种格式持续存储着状态信息,在创建备忘录时需要提供状态信息,备忘录还支持导出状态信息的副本。

希望使用备忘录进行备份和恢复的类型被称为原发器类型Originator,它需要自行实现与备忘录类的交互:

  • exportToMemento:导出内部状态,用于创建一个备忘录对象并返回;
  • setFromMemento:接收一个备忘录对象为参数,从其中获取状态信息,用于重置自身的内部状态。

为了更方便地对备忘录进行管理,我们还可以实现一个管理者类型Caretaker,它是存储备忘录对象的栈的简易封装: 提供pushMemento接口来存储备忘录对象,提供popMemento接口导出栈顶的备忘录对象。

示例代码如下

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

// 备忘录类
class Memento {
private:
std::string m_state;

public:
explicit Memento(std::string s) : m_state(std::move(s)) {}

std::string getState() const { return m_state; }
};

// 原发器类
class Originator {
private:
std::string m_state;

public:
void setState(const std::string &s) {
std::cout << "Setting state to: " << s << std::endl;
m_state = s;
}

std::string getState() const { return m_state; }

Memento exportToMemento() {
std::cout << "Saving state to Memento: " << m_state << std::endl;
return Memento(m_state);
}

void setFromMemento(const Memento &memento) {
m_state = memento.getState();
std::cout << "Restored state from Memento: " << m_state << std::endl;
}
};

// 管理者类
class Caretaker {
private:
std::stack<Memento> m_mementoStack;

public:
void pushMemento(const Memento &memento) { m_mementoStack.push(memento); }

Memento popMemento() {
if (m_mementoStack.empty()) {
throw std::runtime_error("No mementos to restore.");
}
Memento memento = m_mementoStack.top();
m_mementoStack.pop();
return memento;
}
};

int main() {
Originator originator;
Caretaker caretaker;

originator.setState("State 1");
caretaker.pushMemento(originator.exportToMemento());

originator.setState("State 2");
caretaker.pushMemento(originator.exportToMemento());

originator.setState("State 3");

originator.setFromMemento(caretaker.popMemento());
originator.setFromMemento(caretaker.popMemento());

return 0;
}

运行结果如下

1
2
3
4
5
6
7
Setting state to: State 1
Saving state to Memento: State 1
Setting state to: State 2
Saving state to Memento: State 2
Setting state to: State 3
Restored state from Memento: State 2
Restored state from Memento: 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
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
137
138
139
140
141
142
143
#include <cstring>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>

// 备忘录类
class Memento {
private:
std::vector<char> m_stateData;

public:
explicit Memento(std::vector<char> data) : m_stateData(std::move(data)) {}

const std::vector<char> &getStateData() const { return m_stateData; }
};

// 原发器类
class Originator {
private:
std::string m_strState;
std::vector<double> m_doubleArray;
bool m_boolState;

public:
void setState(const std::string &str, const std::vector<double> &array,
bool b) {
m_strState = str;
m_doubleArray = array;
m_boolState = b;
std::cout << "Setting state to: " << m_strState << ", {";
for (double f : m_doubleArray) std::cout << f << " ";
std::cout << "}, " << m_boolState << std::endl;
}

Memento exportToMemento() {
std::vector<char> stateData;

// Save string length and string
size_t strLength = m_strState.size();
stateData.resize(sizeof(strLength) + strLength);
std::memcpy(stateData.data(), &strLength, sizeof(strLength));
std::memcpy(stateData.data() + sizeof(strLength), m_strState.data(),
strLength);

// Save double array size and elements
size_t arraySize = m_doubleArray.size();
size_t currentSize = stateData.size();
stateData.resize(currentSize + sizeof(arraySize)
+ arraySize * sizeof(double));
std::memcpy(stateData.data() + currentSize, &arraySize,
sizeof(arraySize));
std::memcpy(stateData.data() + currentSize + sizeof(arraySize),
m_doubleArray.data(), arraySize * sizeof(double));

// Save bool value
currentSize = stateData.size();
stateData.resize(currentSize + sizeof(m_boolState));
std::memcpy(stateData.data() + currentSize, &m_boolState,
sizeof(m_boolState));

std::cout << "Exporting state to Memento" << std::endl;
return Memento(stateData);
}

void setFromMemento(const Memento &memento) {
const std::vector<char> &stateData = memento.getStateData();
auto it = stateData.begin();

// Load string length and string
int64_t strLength = 0;
std::memcpy(&strLength, &(*it), sizeof(strLength));
it += sizeof(strLength);
m_strState = std::string(it, it + strLength);
it += strLength;

// Load double array size and elements
int64_t arraySize = 0;
std::memcpy(&arraySize, &(*it), sizeof(arraySize));
it += sizeof(arraySize);
m_doubleArray.resize(arraySize);
std::memcpy(m_doubleArray.data(), &(*it), arraySize * sizeof(double));
it += arraySize * sizeof(double);

// Load bool value
std::memcpy(&m_boolState, &(*it), sizeof(m_boolState));

std::cout << "Restored state from Memento: " << m_strState << ", {";
for (double f : m_doubleArray) std::cout << f << " ";
std::cout << "}, " << m_boolState << std::endl;
}
};

// 管理者类
class Caretaker {
public:
static void saveMemento(const Memento &memento,
const std::string &filename) {
std::ofstream outFile(filename, std::ios::binary);
if (outFile.is_open()) {
const std::vector<char> &stateData = memento.getStateData();
outFile.write(stateData.data(), (int64_t)stateData.size());
outFile.close();
}
else {
std::cerr << "Unable to open file for writing: " << filename
<< std::endl;
}
}

static Memento loadMemento(const std::string &filename) {
std::ifstream inFile(filename, std::ios::binary);
if (inFile.is_open()) {
std::vector<char> stateData(
(std::istreambuf_iterator<char>(inFile)),
std::istreambuf_iterator<char>());
inFile.close();
std::cout << "Loaded state from file " << filename << std::endl;
return Memento(stateData);
}

std::cerr << "Unable to open file for reading: " << filename
<< std::endl;
throw std::runtime_error("File not found.");
}
};

int main() {
Originator originator;

originator.setState("State1", {1.1, 2.2, 3.3}, true);
Caretaker::saveMemento(originator.exportToMemento(), "state1.bin");

originator.setState("State2", {4.4, 5.5}, false);
Caretaker::saveMemento(originator.exportToMemento(), "state2.bin");

originator.setState("State3", {6.6, 7.7, 8.8, 9.9}, true);

originator.setFromMemento(Caretaker::loadMemento("state2.bin"));
originator.setFromMemento(Caretaker::loadMemento("state1.bin"));

return 0;
}

运行结果如下

1
2
3
4
5
6
7
8
9
Setting state to: State1, {1.1 2.2 3.3 }, 1
Exporting state to Memento
Setting state to: State2, {4.4 5.5 }, 0
Exporting state to Memento
Setting state to: State3, {6.6 7.7 8.8 9.9 }, 1
Loaded state from file state2.bin
Restored state from Memento: State2, {4.4 5.5 }, 0
Loaded state from file state1.bin
Restored state from Memento: State1, {1.1 2.2 3.3 }, 1

这里我们实际上是在模仿实现MATLAB的loadsave函数,但是实际效果远远比不了MATLAB,MATLAB有一套完整的机制来实现任意对象的序列化和反序列化,不需要我们对自定义类型进行手动实现。