File tree Expand file tree Collapse file tree 10 files changed +231
-1
lines changed
Expand file tree Collapse file tree 10 files changed +231
-1
lines changed Original file line number Diff line number Diff line change 4848
4949[ 中介者模式 Mediator] ( doc/19-中介者.md )
5050
51- 备忘录模式 Memento
51+ [ 备忘录模式 Memento] ( doc/20-备忘录.md )
5252
5353观察者模式 Observer
5454
Original file line number Diff line number Diff line change 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} )
Original file line number Diff line number Diff line change 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+ }
Original file line number Diff line number Diff line change 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+ }
Original file line number Diff line number Diff line change 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__
Original file line number Diff line number Diff line change 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 )
Original file line number Diff line number Diff line change 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
You can’t perform that action at this time.
0 commit comments