2021/11/29

#include <iostream>
#include <stack>
#include <string>
using namespace std;

class Command
{
public:
	Command(){}
	virtual ~Command(){}

	virtual void Execute() = 0;
};


class InputCommand : public Command
{
	public:

		InputCommand( const std::string &input )
		{
			mInput = input;
		}
		~InputCommand()
		{}

		void Execute()
		{
			printf( "当前字符串: %s\n", mInput.c_str() );
		}

private:

	std::string mInput;
};

class Commander
{
public:
	Commander( Command *pCmd )
	{
		//最初的命令数据
		mUndo.push( pCmd );
	}
	~Commander()
	{
		while( false == mUndo.empty() )
		{
			delete mUndo.top();
			mUndo.pop();
		}
		while( false == mRedo.empty() )
		{
			delete mRedo.top();
			mRedo.pop();
		}
	}

	void ExecuteCommand( Command *pCmd )
	{
		pCmd->Execute();
		mUndo.push( pCmd );
	}

	void Undo()
	{
		if( mUndo.size() < 2 )
		{
			//无法后退撤销没有数据
			printf( "撤销失败.\n" );
			return;
		}

		printf( "撤销:\n" );

		//当前命令
		auto pCmd = mUndo.top();

		//保存当前命令
		mRedo.push( pCmd );

		//弹出
		mUndo.pop();

		//还原到上个命令
		pCmd = mUndo.top();

		pCmd->Execute();
	}

	void Redo()
	{
		if( mRedo.empty() )
		{
			//无法前进重做没有数据
			printf( "重写失败.\n" );
			return;
		}

		printf( "重写:\n" );

		auto pCmd = mRedo.top();

		pCmd->Execute();

		mRedo.pop();

		mUndo.push( pCmd );
	}

private:
	std::stack< Command* > mUndo;
	std::stack< Command* > mRedo;
};

int main()
{
	//默认没有输入字符串可以是空,这里为了演示赋值一个特殊的字符串
	Commander *p = new Commander( new InputCommand( "[empty]" ) );

	//输入1234
	p->ExecuteCommand( new InputCommand( "123" ) );
	//输入567
	p->ExecuteCommand( new InputCommand( "567" ) );
	//输入xxx
	p->ExecuteCommand( new InputCommand( "xxx" ) );

	//执行一次undo 撤销到 567
	p->Undo();
	//执行一次undo 撤销到 1234
	p->Undo();

	//undo后中间输入新字符串 insert 覆盖 1234
	p->ExecuteCommand( new InputCommand( "insert" ) );

	//执行一次undo 撤销到 1234
	p->Undo();

	//执行一次undo 撤销到最初情况 [empty]
	p->Undo();

	//执行失败已经undo 到最原始情况
	p->Undo();

	//执行一次redo 重做到 1234
	p->Redo();
	//执行一次redo 重做到 insert
	p->Redo();
	//执行一次redo 重做到 567
	p->Redo();

	//redo后中间输入新字符串 insert again 覆盖 567
	p->ExecuteCommand( new InputCommand( "insert again" ) );

	//执行一次undo 撤销到567
	p->Undo();

	//执行一次redo 重做到 insert again
	p->Redo();

	//执行一次redo 重做到 xxx
	p->Redo();

	//执行失败已经redo 到最新情况
	p->Redo();
	delete p;
	return 0;
}

  

posted @ 2021-11-29 21:23  小强哥in  阅读(74)  评论(0编辑  收藏  举报