Skip to content

Commit 34558ed

Browse files
committed
add memento
1 parent dfbc0fc commit 34558ed

File tree

10 files changed

+231
-1
lines changed

10 files changed

+231
-1
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848

4949
[中介者模式 Mediator](doc/19-中介者.md)
5050

51-
备忘录模式 Memento
51+
[备忘录模式 Memento](doc/20-备忘录.md)
5252

5353
观察者模式 Observer
5454

code/19_memento/CMakeLists.txt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
cmake_minimum_required(VERSION 3.0)
2+
PROJECT(memento_test)
3+
4+
include(CheckCXXCompilerFlag)
5+
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
6+
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
7+
8+
# 使用变量设置编译标志
9+
if(COMPILER_SUPPORTS_CXX11)
10+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
11+
elseif(COMPILER_SUPPORTS_CXX0X)
12+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
13+
else()
14+
message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
15+
endif()
16+
17+
18+
SET(SRC_LIST client.cpp)
19+
SET(PATTERN_SRC memento_types.cpp)
20+
21+
include_directories(./)
22+
23+
ADD_EXECUTABLE(memento_test ${SRC_LIST} ${PATTERN_SRC})

code/19_memento/client.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#include "memento_types.h"
2+
3+
int main()
4+
{
5+
Player player1;
6+
StepsManager stepManager;
7+
cout << "-----------" << endl;
8+
stepManager.push(player1.doAction("车2平5"));
9+
stepManager.push(player1.doAction("兵3进1"));
10+
stepManager.push(player1.doAction("兵4平1"));
11+
12+
player1.applyAction(stepManager.pop());
13+
player1.applyAction(stepManager.pop());
14+
player1.applyAction(stepManager.pop());
15+
cout << "-----------" << endl;
16+
return 0;
17+
}

code/19_memento/memento_types.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#include "memento_types.h"
2+
3+
Player::Player()
4+
{
5+
}
6+
7+
Player::~Player()
8+
{
9+
}
10+
11+
Step *Player::doAction(std::string state)
12+
{
13+
this->state_ = state;
14+
Step *step = new Step(this->state_);
15+
cout << "Do step:" << this->state_ << endl;
16+
return step;
17+
}
18+
19+
void Player::applyAction(Step *step)
20+
{
21+
if (step)
22+
{
23+
this->state_ = step->getState();
24+
cout << "Back step:" << this->state_ << endl;
25+
}
26+
}
27+
28+
StepsManager::StepsManager()
29+
{
30+
}
31+
32+
StepsManager::~StepsManager()
33+
{
34+
}
35+
36+
void StepsManager::push(Step *step)
37+
{
38+
if (step)
39+
{
40+
mementos.push(step);
41+
}
42+
}
43+
44+
Step *StepsManager::pop()
45+
{
46+
Step *step = NULL;
47+
if (mementos.empty())
48+
return step;
49+
step = mementos.top();
50+
mementos.pop();
51+
return step;
52+
}

code/19_memento/memento_types.h

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#ifndef __MEMENTO_TYPES_H__
2+
#define __MEMENTO_TYPES_H__
3+
4+
#include <iostream>
5+
#include <string>
6+
#include <stack>
7+
using namespace std;
8+
9+
class Step
10+
{
11+
public:
12+
Step(std::string state) : state_(state) {}
13+
~Step() {}
14+
inline std::string getState()
15+
{
16+
return state_;
17+
}
18+
19+
private:
20+
std::string state_;
21+
};
22+
23+
class Player
24+
{
25+
public:
26+
Player();
27+
~Player();
28+
Step *doAction(std::string state);
29+
void applyAction(Step *step);
30+
31+
private:
32+
std::string state_;
33+
};
34+
35+
class StepsManager
36+
{
37+
public:
38+
StepsManager();
39+
~StepsManager();
40+
void push(Step *step);
41+
Step *pop();
42+
43+
private:
44+
std::stack<Step *> mementos;
45+
};
46+
47+
#endif // __MEMENTO_TYPES_H__

code/19_memento/result.png

3.59 KB
Loading

doc/20-备忘录.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# 备忘录
2+
3+
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后当需要时能将该对象恢复到原先保存的状态。该模式又叫快照模式
4+
5+
备忘录模式能记录一个对象的内部状态,当用户后悔时能撤销当前操作,使数据恢复到它原先的状态。
6+
7+
## UML
8+
9+
* 发起人(Originator)角色:记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,实现其他业务功能,它可以访问备忘录里的所有信息。
10+
* 备忘录(Memento)角色:负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人。
11+
* 管理者(Caretaker)角色:对备忘录进行管理,提供保存与获取备忘录的功能,但其不能对备忘录的内容进行访问与修改。
12+
13+
![figure19_memento](img/figure19_memento.png)
14+
15+
## 优缺点
16+
17+
* 优点
18+
* 提供了一种可以恢复状态的机制。当用户需要时能够比较方便地将数据恢复到某个历史的状态。
19+
* 实现了内部状态的封装。除了创建它的发起人之外,其他对象都不能够访问这些状态信息。
20+
* 简化了发起人类。发起人不需要管理和保存其内部状态的各个备份,所有状态信息都保存在备忘录中,并由管理者进行管理,这符合单一职责原则。
21+
22+
* 缺点
23+
* 资源消耗大。如果要保存的内部状态信息过多或者特别频繁,将会占用比较大的内存资源。
24+
25+
26+
## 使用场景
27+
28+
* 需要保存与恢复数据的场景,如玩游戏时的中间结果的存档功能。
29+
* 需要提供一个可回滚操作的场景,如 Word、记事本、Photoshop,Eclipse 等软件在编辑时按 Ctrl+Z 组合键,还有数据库中事务操作。
30+
31+
32+
## 用例
33+
34+
在常见的象棋或棋类游戏中,常常允许悔棋.
35+
36+
![figure19_memento_case](img/figure19_memento_case.png)
37+
38+
[code](../code/19_memento)
39+
40+
41+
![result](../code/19_memento/result.png)

doc/img/figure19_memento.png

14 KB
Loading

doc/img/figure19_memento_case.png

14.9 KB
Loading

doc/uml/19_memento.pu

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
@startuml "figure19_memento"
2+
caption figure 19: Memento
3+
4+
class Originator{
5+
- state: State
6+
+ createMemento() : Memento
7+
+ restoreMemento(memento:Memento) : void
8+
}
9+
10+
class Memento{
11+
- state: State
12+
+ getState(): State
13+
}
14+
15+
class Caretaker{
16+
- memento: Memento
17+
+ getMemento(): Memento
18+
+ setMemento(memento:Memento): void
19+
}
20+
21+
Originator --> Memento
22+
23+
Caretaker o--> Memento
24+
@enduml
25+
26+
27+
@startuml "figure19_memento_case"
28+
caption figure 19: Memento Case
29+
30+
class Step{
31+
- state: std::string
32+
+ getState(): std::string
33+
}
34+
35+
class Player{
36+
- state: std::string
37+
+ doAction(state:std::string) : Step*
38+
- applyAction(step:Step*): void
39+
}
40+
41+
class StepsManager{
42+
- mementos : std::stack<Step*>
43+
+ push(step:Step*)
44+
+ pop(): Step*
45+
}
46+
47+
Player --> Step
48+
StepsManager o--> Step
49+
50+
@enduml

0 commit comments

Comments
 (0)