备忘录模式 – 状态保存,恢复原状
备忘录模式是一种行为设计模式,允许在不暴露对象实现细节的情况下保存和恢复对象的内部状态。这种模式特别适用于实现撤销(Undo)操作或者是需要保存对象状态以便将来恢复的场景。
组成
备忘录模式通常涉及三个关键角色:
- 发起人(Originator):这是需要保存其状态以便以后恢复的对象。
- 备忘录(Memento):用于存储发起人对象的内部状态。备忘录应保护其内容不被发起人以外的对象所访问。
- 管理者(Caretaker):负责保存备忘录,但不对备忘录内容进行操作或检查。
优势
- 封装性:备忘录模式很好地封装了对象的状态。通过使用备忘录,对象的状态可以保存在备忘录对象中,而不需要暴露对象的内部结构。这有助于保持对象的封装性和数据的完整性。
- 撤销操作:备忘录模式提供了一种实现撤销(Undo)操作的机制。用户可以方便地回退到某个特定的状态,而不需要了解对象状态的具体实现。
- 保存历史状态:备忘录模式允许保存对象的历史状态,这对于实现某些功能,如历史记录查看、状态回滚等,非常有用。
灵活性:备忘录模式允许在不同的时间保存对象的不同状态,提供了很高的灵活性。
使用场景
- 撤销功能:在需要提供撤销操作的应用程序中,如文本编辑器、图形编辑工具、游戏等,备忘录模式可以用来保存操作前的状态,以便用户可以撤销他们的操作。
- 事务回滚:在需要事务支持的系统中,如果某个操作失败,可以使用备忘录模式保存的状态来回滚到操作前的状态。
- 状态快照:在需要保存对象状态快照,以便将来可能恢复到这些状态的应用中,如软件版本控制、保存游戏进度等。
- 比较历史状态:在需要比较对象的当前状态与历史状态的应用中,备忘录模式提供了一种方便的实现方式。
实现
- 发起人和备忘录
// 发起人
class Originator {
std::string state;
public:
// 备忘录
class Memento {
std::string state;
public:
Memento(const std::string& state) : state(state) {}
std::string getState() const {
return state;
}
};
void setState(const std::string& state) {
this->state = state;
std::cout << "State set to: " << state << std::endl;
}
std::string getState() const {
return state;
}
// 保存状态
std::shared_ptr<Memento> saveStateToMemento() {
return std::make_shared<Memento>(state);
}
// 恢复状态
void getStateFromMemento(const std::shared_ptr<Memento>& memento) {
state = memento->getState();
}
};
- 管理者
class Caretaker {
std::vector<std::shared_ptr<Originator::Memento>> mementoList;
public:
void add(const std::shared_ptr<Originator::Memento>& state) {
mementoList.push_back(state);
}
std::shared_ptr<Originator::Memento> get(int index) {
return mementoList.at(index);
}
};
- 测试
int main() {
Originator originator;
Caretaker caretaker;
originator.setState("State #1");
originator.setState("State #2");
caretaker.add(originator.saveStateToMemento());
originator.setState("State #3");
caretaker.add(originator.saveStateToMemento());
originator.setState("State #4");
std::cout << "Current State: " << originator.getState() << std::endl;
originator.getStateFromMemento(caretaker.get(0));
std::cout << "First saved State: " << originator.getState() << std::endl;
originator.getStateFromMemento(caretaker.get(1));
std::cout << "Second saved State: " << originator.getState() << std::endl;
return 0;
}
- 结果
State set to: State #1
State set to: State #2
State set to: State #3
State set to: State #4
Current State: State #4
First saved State: State #2
Second saved State: State #3