memento模式是设计模式中最枯燥的一种,没有用到继承、多态、甚至组合,方法也好理解,最不好理解的是三个角色类及其分工与配合,其中两个非常普通,originator(原发器)是产生memento的类,memento是保存状态信息和其他信息的类,而careTaker是管理memento的管理器角色。
这三个类设计非常合理,最大的工作量是careTaker的设计。redo和undo的memento都在这里存储和取回。如下面的careTaker如果仅有一个stack的话,就仅能实现undo,而不能实现redo了。
这个程序没有考虑到资源管理,引入shared_ptr显得复杂。
h文件:
#ifndef MEMENTO_H
#define MEMENTO_H
#include <iostream>
#include <string>
#include <stack>
#include <algorithm>
using namespace std;
class userMemento
{
std::string account;
std::string pw;
std::string telNom;
public:
userMemento(string ac,string passw,string tel):account(ac),pw(passw),telNom(tel)
{
}
std::string getAccount ( ) const
{
return account;
}
void setAccount (std::string val)
{
account = val;
}
std::string getPw ( ) const
{
return pw;
}
void setPw (std::string val)
{
pw = val;
}
std::string getTelNom ( ) const
{
return telNom;
}
void setTelNom (std::string val)
{
telNom = val;
}
};
class userInfo
{
std::string account;
std::string pw;
std::string telNom;
public:
std::string getAccount ( ) const
{
return account;
}
void setAccount (std::string val)
{
account = val;
}
std::string getPw ( ) const
{
return pw;
}
void setPw (std::string val)
{
pw = val;
}
std::string getTelNom ( ) const
{
return telNom;
}
void setTelNom (std::string val)
{
telNom = val;
}
userMemento* crtMemento()
{
return new userMemento (account, pw, telNom);
}
void restorMemento(const userMemento* menentoP)
{
if(menentoP)
{
account = menentoP->getAccount ( );
pw = menentoP->getPw ( );
telNom = menentoP->getTelNom ( );
}
else
{
account.clear ( );
pw.clear ( );
telNom.clear();
}
}
void printInfo()
{
std::cout << " this->account : " << this->account << std::endl;
std::cout << " this->pw : " << this->pw << std::endl;
std::cout << " this->telNom : " << this->telNom << std::endl;
}
};
class careTaker
{
typedef std::stack<userMemento*> CollType;
CollType undo_list,redo_list;
void emptyStack(CollType& stk)
{
while (!stk.empty ( ))
stk.pop ( );
}
public:
void store(userMemento* um)
{
undo_list.push (um);
emptyStack (redo_list);
}
userMemento* undo()
{
if (!undo_list.empty())
{
userMemento* um = undo_list.top ( );
redo_list.push (um);
undo_list.pop ( );
return um;
}
return 0;
}
userMemento* redo()
{
if (!redo_list.empty())
{
userMemento* um = redo_list.top ( );
undo_list.push (um);
redo_list.pop ( );
return um;
}
return 0;
}
};
#endif //MEMENTO_H
cpp文件
// memento.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "memento.h"
int _tmain(int argc, _TCHAR* argv[])
{
boost::shared_ptr<userInfo> ui(new userInfo);
ui->setAccount ("kang");
ui->setPw ("1234&*&7^");
ui->setTelNom ("18949338041");
ui->printInfo ( );
boost::shared_ptr<careTaker> tak(new careTaker);
tak->store (ui->crtMemento ( ));
ui->setAccount ("li");
ui->setPw ("4&*&7^");
ui->setTelNom ("1891111111111");
ui->printInfo ( );
tak->store (ui->crtMemento ( ));
tak->undo ( );
ui->restorMemento (tak->undo());
ui->printInfo ( );
std::cout << "redo..............." << std::endl;
ui->restorMemento (tak->redo ( ));
ui->printInfo ( );
ui->restorMemento (tak->redo ( ));
ui->printInfo ( );
ui->restorMemento (tak->redo ( ));
ui->printInfo ( );
return 0;
}
真实的careTaker应该是这个样子的,加入资源管理,经过智能指针的包装,才有了Java或者C#的方便,但确实累赘很多了:
class careTaker
{
typedef boost::shared_ptr<userMemento> sharedMemento;
typedef std::stack<sharedMemento> StackType;
StackType undo_list,redo_list;
void emptyStack(StackType& stk)
{
while (!stk.empty ( ))
stk.pop ( );
}
public:
void store(sharedMemento um)
{
undo_list.push (um);
emptyStack (redo_list);
}
sharedMemento undo()
{
if (!undo_list.empty())
{
sharedMemento um = undo_list.top ( );
redo_list.push (um);
undo_list.pop ( );
return um;
}
return sharedMemento(0);
}
sharedMemento redo()
{
if (!redo_list.empty())
{
sharedMemento um = redo_list.top ( );
undo_list.push (um);
redo_list.pop ( );
return um;
}
return sharedMemento(0);
}
};