备忘录模式C++实现
1定义Memento pattern
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将该对象恢复到原先的状态
2类图
3实现
class Originator
{
private:
string state;
public:
string getState();
void setState(string &x);
Memento creatMemento()
{
return new Memento(state);
}
void restoreMemento(Memento men)
{
setState(men.getState());
}
};
class Memento
{
public:
Memento(string st)
:state(st)
{}
string getState()
{
return state;
}
void setState(string st)
{
state = st;
}
};
//备忘录管理员角色
class Caretaker
{
private:
Memento memento;
Memento getMemento()
{return memento;}
void setMemento(string st)
{memento = st;}
};
class Client
{
public:
void operator()()
{
Originator or= new Originator();
Caretaker ca = new Caretaker();
//管理员备忘记录设置为用户定义为备忘状态
ca.setMemento(or.createMemento());
//用户重新会退到管理员记录的某一状态
or.restoreMemento(ca.getMemento());
}
};
4应用
使用场景
需要提供保存和恢复数据的相关状态场景
提供一个可回滚rollback操作
需要监控的副本场景。
数据库连接的事务管理就是备忘录模式
注意事项:
备忘录的声明期:作用在最近的代码。不使用就立即删除。..备忘录不是华佗在世,起死回生
备忘录的性能:不能用在for中,不能用频繁建立。消耗资源太多,这会是设计重构的前兆
5扩展
clone方式的备忘录
实现
class Originator :public Cloneable
{
private:
string state;
public:
void setState(string st);
Originator creatorMemento()
{
return clone();
}
restoreMemento(Originator or)
{
setState(or.getState);
}
Originator clone()
{
//其实就是拷贝构造一个
}
};
class Caretaker
{
private:
Originator or;
Originator getOriginator()
{
return or;
}
void setOriginator(Originator originator)
{
or = originator;
}
}
既然可以合并备忘录角色,那么管理员也是可以合并的
∴
class Originator :public Cloneable
{
private:
Originator* _backup;
string _state;
public:
Originator(const Originator& or)
{}
void setState();
void creatMemento()
{
_bcakup = new Originator(*this);
}
void restoreMemento()
{
assert(_backup);
setStat(_backup->getState);
}
};
注:因为clone方式的备忘录可能会因为深浅拷贝问题而复杂,所以clone方式的备忘录适用简单的场景
②多状态备忘录
在Originator中封装多个状态,而Memento则保存一个HashMap 的state
③多备份的备忘录
注:管理员角色封装一的HashMap封装一个备忘录而非备忘状态
eg
class Caretaker
{
private:
HashMap<string,Memento> memMap;
public:
Memento getMemento(stirng index)
{}
void setMemento(string index,Memento me)
{
memMap.put(index,me);
}
};
void Test
{
Originator or = new Originator();
Caretaker ca = new Caretaker();
ca.setMemento("001",or.createMemento());
ca.setMemento("002",or.createMemento());
or.restoreMemento(ca.getMemento("001"));
}
注:该模式下应当注意备忘录上限,控制内存
提升:提供权限问题
class Originator
{
private:
string state;
public:
void setState(string st);
Imemento createMemento()
{
return new Memento(state);
}
void restoreMemento(Imemento me)
{
setState(me.getState());
}
private:
//内置类,实现
class Memento :public IMemento
{
private:
string state;
Memento(string st)
{
state = st;
}
string getState();
void setState(string st);
};
};
class Imemento
{
public:
virtual ~Imemento()=0;
};
class Caretaker
{
Imemento memento;
public:
Imemento getMemento()
{
return memento;
}
void setMemento(Imemento mem)
{
memento = mem;
}
};
注:这里的设计方案:双接口设计,一个是业务的正常接口,实现必要的业务逻辑,宽接口;另一个则是空接口,什么方法都没有,目的是提供给子系统外的模块访问,窄接口。窄接口中没有任何操纵数据的方法,所以是相对安全的。