命令模式的应用之可撤销恢复操作的计算器

xiaoxiao2021-02-28  14

深度理解命令模式

(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; }
转载请注明原文地址: https://www.6miu.com/read-1750055.html

最新回复(0)