命令模式的应用之可撤销/恢复操作的计算器
程序员文章站
2022-03-10 17:17:56
...
深度理解命令模式
(1)参数化配置:用不同的命令对象,去参数化配置客户的请求。
(2)可撤销的操作:
①补偿式(反操作式):如被撤销的操作是加的功能,那么反操作就是减的功能。
②存储恢复式:把操作前的状态记录下来,然后要撤销操作时就直接恢复回去就可以了。(该种方式会放到备忘录模式中进行讲解)
【编程实验】可撤销/恢复操作的计算器
//声明文件
//*********************************************************************************************
//行为型模式:命令模式
//场景:计算器(可撤销的计算)
#include <iostream>
#include <string>
#include <list>
using namespace std;
//***************************************Receiver*******************
//操作运算的接口
//运算类,真正实现加减法运算(具体的接收者)
class CCalculator{
private:
int iResult;
public:
void SetResult(int result);
int GetResult();
void Add(int num);
void Sub(int num);
};
//*************************Command***********************
//命令接口,支持可撤销操作
class CCalcCmd{
public:
virtual void Execute() = 0;//执行命令的操作
virtual void Undo() = 0; //执行撤销的操作
};
//具体的加法命令
class CAddCmd : public CCalcCmd{
private://持有具体执行计算的对象(命令的接收者)
CCalculator* pCalc;
int iNum;//要加上的数据
public:
CAddCmd(CCalculator* calc, int num);
void Execute();
void Undo();
};
//具体的减法命令
class CSubCmd : public CCalcCmd{
private://持有具体执行计算的对象(命令的接收者)
CCalculator* pCalc;
int iNum; //要减去的数据
public:
CSubCmd(CCalculator* calc, int num);
void Execute();
void Undo();
};
//*****************************Invoker************************************
//计算器类,计算器上有加法按钮和减法按钮
class CController{
private:
CCalcCmd* pAddCmd;//加法命令对象
CCalcCmd* pSubCmd; //减法命令对象
list<CCalcCmd*> lstUndo; //命令的操作历史记录,在撤销的时候用
list<CCalcCmd*> lstRedo; //命令被撤销的历史记录,在恢复时使用
public:
CController(CCalcCmd* addcmd, CCalcCmd* subcmd);
void SetAddCmd(CCalcCmd* addcmd);
void SetSubCmd(CCalcCmd* subcmd);
//提供给客户使用,执行加法, 减法功能, 把操作记录到历史记录里面
void Add();
void Sub();
void Undo();
void Redo();
};
//实现文件
//***************************************Receiver*******************
//操作运算的接口
//运算类,真正实现加减法运算(具体的接收者)
void CCalculator::SetResult(int result){iResult = result;}
int CCalculator::GetResult(){return iResult;}
void CCalculator::Add(int num){ iResult += num;}
void CCalculator::Sub(int num){ iResult -= num;}
//*************************Command***********************
//命令接口,支持可撤销操作
//具体的加法命令
CAddCmd::CAddCmd(CCalculator* calc, int num){pCalc = calc; iNum = num;}
void CAddCmd::Execute(){pCalc->Add(iNum);}
void CAddCmd::Undo(){pCalc->Sub(iNum);}
//具体的减法命令
CSubCmd::CSubCmd(CCalculator* calc, int num){pCalc = calc; iNum = num;}
void CSubCmd::Execute(){pCalc->Sub(iNum);}
void CSubCmd::Undo(){pCalc->Add(iNum);}
//*****************************Invoker************************************
//计算器类,计算器上有加法按钮和减法按钮
CController::CController(CCalcCmd* addcmd, CCalcCmd* subcmd){
pAddCmd = addcmd; pSubCmd = subcmd;
}
void CController::SetAddCmd(CCalcCmd* addcmd){pAddCmd = addcmd;}
void CController::SetSubCmd(CCalcCmd* subcmd){pSubCmd = subcmd;}
//提供给客户使用,执行加法, 减法功能, 把操作记录到历史记录里面
void CController::Add(){ pAddCmd->Execute(); lstUndo.push_back(pAddCmd);}
void CController::Sub(){ pSubCmd->Execute(); lstUndo.push_back(pSubCmd);}
void CController::Undo(){
if(lstUndo.size() < 1) return;
//取出最后一个命令来撤销, 然后把最后一个命令删除掉
CCalcCmd* pCmd = lstUndo.back(); lstUndo.pop_back();
//如果还有恢复功能,那就把这个命令记录到恢复历史列表中
pCmd->Undo(); lstRedo.push_back(pCmd);
cout << "lstUndo.size() = " << lstUndo.size() << ", lstRedo.size() = " << lstRedo.size() << endl;
}
void CController::Redo(){
if(lstRedo.size() < 1) return;
//取出最后一个命令来重做, 然后把最后一个命令删除掉
CCalcCmd* pCmd = lstRedo.back(); lstRedo.pop_back();
//把这个命令记录到可撤销的历史记录里面
pCmd->Execute(); lstUndo.push_back(pCmd);
cout << "lstUndo.size() = " << lstUndo.size() << ", lstRedo.size() = " << lstRedo.size() << endl;
}
//测试客户端
void main()
{
CCalculator oCalculator; oCalculator.SetResult(0);//创建接收者
CAddCmd oAdd5(&oCalculator, 5);//创建命令对象,并组装命令和接收者
CSubCmd oSub3(&oCalculator, 3);
CAddCmd oAdd10(&oCalculator, 10);
CSubCmd oSub4(&oCalculator, 4);
CController oController(&oAdd5, &oSub3);//把命令设置到持有者
oController.Add();// 模拟按下按钮,测试一下
cout << "一次加法运算后的结果为:" << oCalculator.GetResult() << endl;
oController.Sub();
cout << "一次减法运算后的结果为:" << oCalculator.GetResult() << endl;
oController.SetAddCmd(&oAdd10);
oController.Add();
cout << "一次加法运算后的结果为:" << oCalculator.GetResult() << endl;
//测试撤销
oController.Undo();
cout << "撤销一次后的结果为:" << oCalculator.GetResult() << endl;
oController.Undo();
cout << "再次撤销一次后的结果为:" << oCalculator.GetResult() << endl;
//测试恢复
oController.Redo();
cout << "恢复操作一次后的结果为:" << oCalculator.GetResult() << endl;
oController.Redo();
cout << "再次恢复操作一次后的结果为:" << oCalculator.GetResult() << endl;
}
上一篇: 命令模式例题——计算器(撤销、恢复)
下一篇: Python基础之模块相关知识总结
推荐阅读