总体思路

  • 利用Memento模式,为每一个执行命令之前的对象的状态创建备份。
  • 利用Command模式,将命令的调用和操作的实现解耦。
  • 通过维护一个命令和备份相对应的数组,将命令和当前对象的备份同步保存起来。
  • 设置一个当前数组的游标,标识当前回退或重做的进度。

代码实现

#include <vector>
#include <iostream>class DoubleNumber;//备忘录DoubleNumberMemento只能在DoubleNumber内部创建
class DoubleNumberMemento
{//声明DoubleNumber为友元类friend class DoubleNumber;
public:~DoubleNumberMemento() {}private://接口都声明为privateDoubleNumberMemento(double dblValue) : m_dblValue(dblValue) {}double GetNumber(){return m_dblValue;}//记录DoubleNumber的原始状态double m_dblValue;
};//DoubleNumber类
class DoubleNumber
{
public:DoubleNumber(double dblValue) : m_dblValue(dblValue) {}~DoubleNumber() {}//三倍计算void Triple(){m_dblValue *= 3.0;}//两倍计算void Double(){m_dblValue *= 2.0;}//显示数据void ShowNumber(){std::cout << m_dblValue << std::endl;}//创建备忘录DoubleNumberMemento* CreateMemento(){return new DoubleNumberMemento(m_dblValue);}//从备忘录恢复void ReinstateMemento(DoubleNumberMemento* pMem){m_dblValue = pMem->GetNumber();}private:double m_dblValue;
};//命令模式
class CalcCommand
{
public:typedef void(DoubleNumber::*Action)();//初始化计算命令,传入数据和计算符CalcCommand(DoubleNumber* pNum, Action action){_receiver = pNum;_action = action;}//执行命令void Execute(){//先备份m_vecMemento.push_back( _receiver->CreateMemento());m_vecCmd.push_back(this);nCurCmd++;(_receiver->*_action)();}//撤销static void Undo(){//到底了if (nCurCmd == 0){return ;}m_vecCmd[nCurCmd - 1]->_receiver->ReinstateMemento(m_vecMemento[nCurCmd - 1]);nCurCmd--;}//重做static void Redo(){//到顶了if (nCurCmd >= m_vecMemento.size()){return ;}(m_vecCmd[nCurCmd]->_receiver->*(m_vecCmd[nCurCmd]->_action))();nCurCmd++;}//释放内存static void Free(){for (int i = 0; i < m_vecCmd.size(); i++){delete m_vecCmd[i];delete m_vecMemento[i];}}
private:DoubleNumber *_receiver;Action _action;//静态变量,记录历史命令static std::vector<CalcCommand*> m_vecCmd;//静态变量,记录备忘录static std::vector<DoubleNumberMemento*> m_vecMemento;//静态变量,命令序号游标static int nCurCmd;
};std::vector<CalcCommand*> CalcCommand::m_vecCmd;
std::vector<DoubleNumberMemento*> CalcCommand::m_vecMemento;
int CalcCommand::nCurCmd = 0;void main()
{DoubleNumber *object = new DoubleNumber(256.0);object->ShowNumber();CalcCommand* cmdDouble = new CalcCommand(object, &DoubleNumber::Double);CalcCommand* cmdTriple = new CalcCommand(object, &DoubleNumber::Triple);cmdDouble->Execute();cmdTriple->Execute();object->ShowNumber();CalcCommand::Undo();CalcCommand::Undo();object->ShowNumber();CalcCommand::Redo();CalcCommand::Redo();object->ShowNumber();CalcCommand::Free();delete object;
}

组合使用Memento模式与Command模式实现多级Redo和Undo相关推荐

  1. 行为模式之Command模式

    1.意图 将一个请求封装为一个对象,从而你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤消的操作. 2.适用性 在以下情况下使用 (1)抽象出待执行的动作以参数化某对象.你可用 ...

  2. 命令模式(Command模式)详解

    在软件开发系统中,常常出现"方法的请求者"与"方法的实现者"之间存在紧密的耦合关系.这不利于软件功能的扩展与维护.例如,想对行为进行"撤销.重做.记录 ...

  3. java execute 执行成功_【JAVA】设计模式之命令模式(Command模式)的使用分析

    命令模式属于23种设计模式中行为模式中的一个,它也是一种简单实用非常普遍的设计模式. 首先看下GOF对命令模式的定义:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或记录 ...

  4. Java设计模式(8)组合模式(Composite模式)

    Composite定义:将对象以树形结构组织起来,以达成"部分-整体" 的层次结构,使得客户端对单个对象和组合对象的使用具有一致性. Composite比较容易理解,想到Compo ...

  5. Android学习按键事件监听与Command模式

    Android学习按键事件监听与Command模式 - Dufresne - 博客园 Android学习按键事件监听与Command模式 一 Command模式 意图: 将一个请求封装为一个对象,从而 ...

  6. 【设计模式】Command模式

    最近想开始多学习一下工作中代码常常使用的设计模式. 除单例模式,工厂模式之外,command模式用的也是比较多的. 在学习了"正统"的设计模式之后,再来看实际项目代码中使用的类似的 ...

  7. Java设计模式(16)中介模式(Mediator模式)

    Mediator定义:用一个中介对象来封装一系列关于对象交互行为. 为何使用Mediator模式/中介模式 各个对象之间的交互操作非常多,每个对象的行为操作都依赖彼此对方,修改一个对象的行为,同时会涉 ...

  8. Java设计模式(1)工厂模式(Factory模式)

    工厂模式定义:提供创建对象的接口. 为何使用工厂模式 工厂模式是我们最常用的模式了,著名的Jive论坛,就大量使用了工厂模式,工厂模式在Java程序系统可以说是随处可见. 为什么工厂模式是如此常用?因 ...

  9. Java设计模式(10)代理模式(Proxy模式)

    理解并使用设计模式,能够培养我们良好的面向对象编程习惯,同时在实际应用中,可以如鱼得水,享受游刃有余的乐趣. Proxy是比较有用途的一种模式,而且变种较多,应用场合覆盖从小结构到整个系统的大结构,P ...

  10. Chain of Responsibility 模式-----推卸责任模式

    >> ----- 当外部请求程序进行某个处理,但程序暂时无法直接决定由哪个对象负责处理时,就需要推卸责任. 在这种情况下,我们可以考虑将多个对象组成一条职责链,然后按照它们的职责链上的顺序 ...

最新文章

  1. YOLO、SSD、FPN、Mask-RCNN检测模型对比
  2. mysql的二级分区_分布式数据库一级分区和二级分区
  3. Vue.js not detected 解决办法
  4. matplotlib 旋转刻度_Matplotlib数据可视化:文本与坐标轴
  5. vuex 管理vue-router的传值
  6. linux内核的I2C子系统详解1——I2C总线概览、驱动框架概览
  7. 保时捷高管透露曾与苹果洽谈CarPlay之外合作事宜
  8. 2022年“超级818汽车狂欢夜”启动,易车将携手汽车品牌共创内容营销
  9. CentOs6.6安装Python3
  10. 赛前集训前的总结(警醒)
  11. python 闭包,装饰器,random,os,sys,shutil,shelve,ConfigParser,hashlib模块
  12. python中字符串方法总结
  13. CentOS 7忘记root密码解决办法
  14. 强化学习ppt_东台中等专业学校北大青鸟班PPT演讲大赛颁奖典礼顺利举行
  15. BC95-G NB-IOT 模块使用
  16. 【ArcGIS进阶】制作土地利用转移矩阵
  17. 联想电脑无法修复此计算机怎么办,联想一键还原不能用怎么办
  18. 三阶魔方学习(新手入门)
  19. 有关聊天机器人的近两年的优秀论文和开源程序
  20. eclipse右下角出现 linking viewer selection with current editor 而且停不掉 导致eclipse很卡

热门文章

  1. 代码随想录动态规划算法PDF
  2. 软考 系统分析师教程 免费拿走不谢
  3. Unity3D学习笔记——layer
  4. 魔塔类游戏实现源码及关卡生成
  5. epson r1900 清零软件_爱普生打印机清零软件
  6. selenium 实现循环点击_webdriver处理循环点击
  7. VMware15pro安装Windows7虚拟机详细教程
  8. 【PTA】7-1 jmu-Java-01入门-取数字浮点数(5分)
  9. 美国工程管理计算机方向,理工科同学必看!美国工程管理研究生申请大揭秘~...
  10. 同时带多个文件生成软盘镜像的方法