组合使用Memento模式与Command模式实现多级Redo和Undo
总体思路
- 利用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相关推荐
- 行为模式之Command模式
1.意图 将一个请求封装为一个对象,从而你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤消的操作. 2.适用性 在以下情况下使用 (1)抽象出待执行的动作以参数化某对象.你可用 ...
- 命令模式(Command模式)详解
在软件开发系统中,常常出现"方法的请求者"与"方法的实现者"之间存在紧密的耦合关系.这不利于软件功能的扩展与维护.例如,想对行为进行"撤销.重做.记录 ...
- java execute 执行成功_【JAVA】设计模式之命令模式(Command模式)的使用分析
命令模式属于23种设计模式中行为模式中的一个,它也是一种简单实用非常普遍的设计模式. 首先看下GOF对命令模式的定义:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或记录 ...
- Java设计模式(8)组合模式(Composite模式)
Composite定义:将对象以树形结构组织起来,以达成"部分-整体" 的层次结构,使得客户端对单个对象和组合对象的使用具有一致性. Composite比较容易理解,想到Compo ...
- Android学习按键事件监听与Command模式
Android学习按键事件监听与Command模式 - Dufresne - 博客园 Android学习按键事件监听与Command模式 一 Command模式 意图: 将一个请求封装为一个对象,从而 ...
- 【设计模式】Command模式
最近想开始多学习一下工作中代码常常使用的设计模式. 除单例模式,工厂模式之外,command模式用的也是比较多的. 在学习了"正统"的设计模式之后,再来看实际项目代码中使用的类似的 ...
- Java设计模式(16)中介模式(Mediator模式)
Mediator定义:用一个中介对象来封装一系列关于对象交互行为. 为何使用Mediator模式/中介模式 各个对象之间的交互操作非常多,每个对象的行为操作都依赖彼此对方,修改一个对象的行为,同时会涉 ...
- Java设计模式(1)工厂模式(Factory模式)
工厂模式定义:提供创建对象的接口. 为何使用工厂模式 工厂模式是我们最常用的模式了,著名的Jive论坛,就大量使用了工厂模式,工厂模式在Java程序系统可以说是随处可见. 为什么工厂模式是如此常用?因 ...
- Java设计模式(10)代理模式(Proxy模式)
理解并使用设计模式,能够培养我们良好的面向对象编程习惯,同时在实际应用中,可以如鱼得水,享受游刃有余的乐趣. Proxy是比较有用途的一种模式,而且变种较多,应用场合覆盖从小结构到整个系统的大结构,P ...
- Chain of Responsibility 模式-----推卸责任模式
>> ----- 当外部请求程序进行某个处理,但程序暂时无法直接决定由哪个对象负责处理时,就需要推卸责任. 在这种情况下,我们可以考虑将多个对象组成一条职责链,然后按照它们的职责链上的顺序 ...
最新文章
- YOLO、SSD、FPN、Mask-RCNN检测模型对比
- mysql的二级分区_分布式数据库一级分区和二级分区
- Vue.js not detected 解决办法
- matplotlib 旋转刻度_Matplotlib数据可视化:文本与坐标轴
- vuex 管理vue-router的传值
- linux内核的I2C子系统详解1——I2C总线概览、驱动框架概览
- 保时捷高管透露曾与苹果洽谈CarPlay之外合作事宜
- 2022年“超级818汽车狂欢夜”启动,易车将携手汽车品牌共创内容营销
- CentOs6.6安装Python3
- 赛前集训前的总结(警醒)
- python 闭包,装饰器,random,os,sys,shutil,shelve,ConfigParser,hashlib模块
- python中字符串方法总结
- CentOS 7忘记root密码解决办法
- 强化学习ppt_东台中等专业学校北大青鸟班PPT演讲大赛颁奖典礼顺利举行
- BC95-G NB-IOT 模块使用
- 【ArcGIS进阶】制作土地利用转移矩阵
- 联想电脑无法修复此计算机怎么办,联想一键还原不能用怎么办
- 三阶魔方学习(新手入门)
- 有关聊天机器人的近两年的优秀论文和开源程序
- eclipse右下角出现 linking viewer selection with current editor 而且停不掉 导致eclipse很卡