设计模式--备忘录模式C++实现

备忘录模式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;

  }

};

注:这里的设计方案:双接口设计,一个是业务的正常接口,实现必要的业务逻辑,宽接口;另一个则是空接口,什么方法都没有,目的是提供给子系统外的模块访问,窄接口。窄接口中没有任何操纵数据的方法,所以是相对安全的。

 

posted @ 2016-03-30 23:58  狼行博客园  阅读(1790)  评论(0编辑  收藏  举报