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);
}
};