可撤銷可重做的計算器
#include <iostream>
#include <list>
using namespace std;
//Memento抽象類
class Memento
{
//空的
};
//定義命令介面
class Command
{
public:
//執行命令
virtual void execute() = 0;
//撤銷命令,恢復到備忘錄物件記錄的狀態
virtual void undo(Memento* m) = 0;
//重做命令,恢復到備忘錄物件記錄的狀態
virtual void redo(Memento* m) = 0;
//創建備忘錄物件
virtual Memento* createMemento() = 0;
};
//操作運算的介面
class OperationApi
{
public:
virtual int getResult() = 0;
virtual void add(int num) = 0;
virtual void substract(int num) = 0;
//創建保存原發器物件狀態的備忘錄物件
virtual Memento* createMemento() = 0;
//重新設定原發器物件狀態,讓其回到備忘錄物件
//記錄的狀態。
virtual void setMemento(Memento* m) = 0;
};
//命令物件的公共物件,實作各個命令物件的公共方法
class AbstractCommand : public Command
{
protected:
//持有真正的命令實作者物件
OperationApi* operation;
public:
virtual void execute() = 0;
void setOperation(OperationApi* operation)
{
this->operation = operation;
}
void undo(Memento* m)
{
operation->setMemento(m);
}
void redo(Memento* m)
{
operation->setMemento(m);
}
Memento* createMemento()
{
return operation->createMemento();
}
};
//加法命令
class AddCommand : public AbstractCommand
{
private:
int opeNum;
public:
AddCommand(int opeNum)
{
this->opeNum = opeNum;
}
void execute()
{
operation->add(opeNum);
}
};
//減法命令
class SubstractCommand : public AbstractCommand
{
private:
int opeNum;
public:
SubstractCommand(int opeNum)
{
this->opeNum = opeNum;
}
void execute()
{
operation->substract(opeNum);
}
};
//運算類(相當于原發器物件)
//與原來相比,不再提供setResult方法,內部狀態,不允許外部來操作
//添加了createMemento和setMemento方法的實作
//添加實作了一個私有的備忘錄物件
class Operation : public OperationApi
{
private:
int result; //計算結果
//內部類
class MementoImpl: public Memento
{
private:
int result;
public:
MementoImpl(int result)
{
this->result = result;
}
int getResult() {return result;}
};
public:
int getResult(){return result;}
void add(int num){result += num;}
void substract(int num){result -= num;}
Memento* createMemento()
{
MementoImpl* m = new MementoImpl(result);
return m;
}
void setMemento(Memento* m)
{
MementoImpl* impl = (MementoImpl*)m;
result = impl->getResult();
}
};
//計算器類(有加法按鈕、減法按鈕,還有撤銷和恢復按鈕)
class Calculator
{
private:
//命令操作的歷史記錄,在撤銷時用
list<Command*> undoCmds;
//命令被撤銷的歷史記錄,在恢復時用
list<Command*> redoCmds;
//每個命令都有執行前和執行后的兩個狀態
//與之對應,即每執行一個命令,會首先壓入執行前的
//狀態,再壓入執行后的狀態
list<Memento*> undoMementos; //用于撤銷時用
list<Memento*> redoMementos; //用于恢復時用
Command* addCmd;
Command* subCmd;
public:
void setAddCmd(Command* addCmd)
{
this->addCmd = addCmd;
}
void setSubstractCmd(Command* subCmd)
{
this->subCmd = subCmd;
}
//按下加法按鈕
void addPressed()
{
//執行命令前先備份一下。
Memento* m1 = addCmd->createMemento();
//執行命令
addCmd->execute();
//把操作記錄到歷史記錄中
undoCmds.push_back(addCmd);
//執行命令后再備份一下
Memento* m2 = addCmd->createMemento();
//設定到撤銷的歷史記錄中(分別壓入命令執行前、后兩個狀態)
undoMementos.push_back(m1);
undoMementos.push_back(m2);
}
//減法按鈕
void substractPressed()
{
//執行命令前先備份一下。
Memento* m1 = subCmd->createMemento();
//執行命令
subCmd->execute();
//把操作記錄到歷史記錄中
undoCmds.push_back(subCmd);
//執行命令后再備份一下
Memento* m2 = subCmd->createMemento();
//設定到撤銷的歷史記錄中(分別壓入命令執行前、后兩個狀態)
undoMementos.push_back(m1);
undoMementos.push_back(m2);
}
//撤銷操作
void undoPressed()
{
if(undoCmds.size() > 0)
{
//取出最后一個命令來撤銷
Command* cmd = undoCmds.back();
//獲取對應的備忘錄物件
Memento* m2 = undoMementos.back();
undoMementos.pop_back();
Memento* m1 = undoMementos.back();
undoMementos.pop_back();
//撤銷(當然是回到該按鈕執行前的狀態)
cmd->undo(m1);
//加入恢復功能
redoCmds.push_back(cmd);
//把相應的備記錄物件也添加過去
redoMementos.push_back(m1);
redoMementos.push_back(m2);
//從撤銷中洗掉最后一個己執行后的命令)
undoCmds.pop_back();
}
else
{
cout <<"很抱歉,沒有可撤銷的命令!" << endl;
}
}
//恢復操作
void redoPressed()
{
if(redoCmds.size() > 0)
{
//取出最后一個命令來重做
Command* cmd = redoCmds.back();
//獲取對應的備忘錄物件
Memento* m2 = redoMementos.back();
redoMementos.pop_back();
Memento* m1 = redoMementos.back();
redoMementos.pop_back();
//重做(當然是回到該按鈕執行后的狀態)
cmd->redo(m2);
//加入撤銷佇列中
undoCmds.push_back(cmd);
//把相應的備記錄物件也添加過去
undoMementos.push_back(m1);
undoMementos.push_back(m2);
//從重做佇列中洗掉最后一個己執行的命令)
redoCmds.pop_back();
}
else
{
cout <<"很抱歉,沒有可恢復的命令!" << endl;
}
}
};
int main()
{
//1、組裝命令和接收者
//創建接收者
OperationApi* operation = new Operation();
//創建命令
AddCommand addCmd(5);
SubstractCommand subCmd(3);
//組裝命令和接收者
addCmd.setOperation(operation);
subCmd.setOperation(operation);
//2.把命令設定到持有者,就是計算器中
Calculator& cal = *(new Calculator());
cal.setAddCmd(&addCmd);
cal.setSubstractCmd(&subCmd);
//3.模擬按下按鈕,測驗一下
cal.addPressed();
cout << "一次加法運算后的結果:" << operation->getResult() << endl;
cal.substractPressed();
cout << "一次減法運算后的結果:" << operation->getResult() << endl;
//測驗撤銷
cal.undoPressed();
cout << "撤銷一次后的結果:" << operation->getResult() << endl;
cal.undoPressed();
cout << "再撤銷一次后的結果:" << operation->getResult() << endl;
//測驗恢復
cal.redoPressed();
cout << "恢復一次后的結果:" << operation->getResult() << endl;
cal.redoPressed();
cout << "再恢復一次后的結果:" << operation->getResult() << endl;
return 0;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/63014.html
標籤:基礎類
上一篇:華為OJ一道題目,計算字串最后一個單詞的長度,單詞以空格隔開。
下一篇:大神們,求解決方法。
