1. 程式人生 > >2.3 設計模式之命令模式

2.3 設計模式之命令模式

命令模式

# 命令模式

// 命令基類
class command
{
public:
	command() {}
	virtual ~command() {}

public:

	virtual void execute() = 0;
	virtual void undo() = 0;
	virtual void redo() = 0;

	virtual bool canExecute() = 0;
	virtual bool canUndo() = 0;
	virtual bool canRedo() = 0;

	virtual string serialize() = 0;
	virtual void deSerialize(const string data)  = 0;
};

// 命令倉庫
class cmdStorage
{
public:
	cmdStorage() {}
	~cmdStorage() {}

public:
	stack<command*>* operator->() {
		return &storage;
	}

	virtual string serialize() {
		return "";
	};
	virtual void deSerialize(const string data) {};
private:
	stack<command*> storage;
};

// 命令管理
class cmdManager
{
public:
	cmdManager() {}
	~cmdManager() {}

public:
	bool exec(command* cmd) {
		bool ret = cmd->canExecute();
		if (ret) {
			cmd->execute();
			undoStorage->push(cmd);
		}
		return ret;
	}

	bool undo() {
		bool ret = undoStorage->size() > 0 ? true : false;
		if (ret) {
			command* cmd = undoStorage->top();
			undoStorage->pop();
			ret = cmd->canUndo();
			if (ret) {
				cmd->undo();
				redoStorage->push(cmd);
			}
			else {
				cout << "cmd can't undo" << endl;
			}
		}
		else {
			cout << "have no cmd" << endl;
		}
		return ret;
	}

	bool redo(){
		bool ret = redoStorage->size() > 0 ? true : false;
		if (ret) {
			command* cmd = redoStorage->top();
			redoStorage->pop();
			ret = cmd->canRedo();
			if (ret) {
				cmd->redo();
				undoStorage->push(cmd);
			}
			else {
				cout << "cmd can't redo" << endl;
			}
		}
		else {
			cout << "have no cmd" << endl;
		}
		return ret;
	}

private:
	cmdStorage undoStorage;
	cmdStorage redoStorage;
};

// concrete command test

class commandOne: public command
{
public:
	commandOne() {}
	~commandOne() {}

public:
	virtual void execute() {
		cout << "commandOne execute()" << endl;
	}
	virtual void undo() {
		cout << "commandOne undo()" << endl;
	}
	virtual void redo() {
		cout << "commandOne redo()" << endl;
	}

	virtual bool canExecute() {
		return true;
	}
	virtual bool canUndo() {
		return true;
	}
	virtual bool canRedo() {
		return true;
	}

	virtual string serialize() {
		return "";
	}
	virtual void deSerialize(const string data) {
	}

};


class commandTwo : public command
{
public:
	commandTwo() {}
	~commandTwo() {}

public:
	virtual void execute() {
		cout << "commandTwo execute()" << endl;
	}
	virtual void undo() {
		cout << "commandTwo undo()" << endl;
	}
	virtual void redo() {
		cout << "commandTwo redo()" << endl;
	}

	virtual bool canExecute() {
		return true;
	}
	virtual bool canUndo() {
		return true;
	}
	virtual bool canRedo() {
		return true;
	}

	virtual string serialize() {
		return "";
	}
	virtual void deSerialize(const string data) {
	}
};


void  test_command(){
	cmdManager manager;

	commandOne* cmd1 = new	commandOne();
	commandTwo* cmd2 = new	commandTwo();

	// 輸出: 1 2 2 1
	cout << "test exec" << endl;
	manager.exec(cmd1);
	manager.exec(cmd1);
	manager.exec(cmd2);
	manager.exec(cmd2);

	cout << "test undo" << endl;
	manager.undo();
	manager.undo();
	manager.undo();
	manager.undo();
	manager.undo();

	cout << "test redo" << endl;
	manager.redo();
	manager.redo();
	manager.redo();
	manager.redo();
	manager.redo();


	system("pause");
	return EXIT_SUCCESS;
}