命令模式 Command Pattern
1.定义
命令模式将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象,同时支持可撤消的操作。
2.目的:
命令模式是为了解决命令的请求者和命令的实现者之间的耦合关系。
+ 方便对命令的扩展。
+ 可以对多个命令进行统一的控制。
3.模式解析
图示:
经典命令模式包含4个角色:
- 命令(Command)角色:定义命令的统一接口,这是一个抽象角色。
- 具体命令(ConcreteCommand)角色:Command接口的实现者,用来执行具体的命令,实现Execute()方法,某些情况下可以直接用来充当Receiver。
- 接收者(Receiver)角色:命令的实际执行者。
- 请求者(Invoker)角色:命令的请求者,命令模式中最重要的角色。这个角色用来对各个命令进行控制。
4.总结:
命令模式很适合实现诸如撤消,重做,回放,时间倒流之类的功能
5.代码实例:
#pragma once
#include <iostream>
using namespace std;
#include <list>
//命令的实际执行者
class Calculator
{
public:
Calculator():_curr(0){}
void Operation( char _operator , int operand)
{
switch (_operator)
{
case '+' : _curr += operand ; break;
case '-' : _curr -= operand ; break;
case '*' : _curr *= operand ; break;
case '/' : _curr /= operand ; break;
}
cout<<"Current value = "<<_curr<<" ( following " <<_operator << operand << " )" <<endl;
}
private:
int _curr ;
};
//定义命令的统一接口
class Command
{
public:
virtual void Execute() = 0;
virtual void UnExecute() = 0;
};
//Command接口的实现者,用来执行具体的命令
class CalculatorCommand : public Command
{
public:
CalculatorCommand( Calculator* calculator , char t_operator , int operand )
{
_operator = t_operator;
_calculator = calculator;
_operand = operand;
}
char SetOperator( char value )
{
_operator = value;
}
int SetOperand( int value )
{
_operand = value;
}
void Execute()
{
_calculator->Operation(_operator , _operand );
}
void UnExecute()
{
_calculator->Operation( Undo(_operator),_operand );
}
char Undo( char t_operator )
{
switch (_operator)
{
case '+' : return '-';
case '-' : return '+';
case '*' : return '/';
case '/' : return '*';
}
}
private:
char _operator;
int _operand;
Calculator* _calculator;
};
//命令的请求者
class User
{
public:
User():_current(0)
{
_calculator = new Calculator();
}
void Compute( char t_operator , int operand )
{
Command * command = new CalculatorCommand( _calculator , t_operator ,operand );
command->Execute();
_commands.push_back( command );
_current++ ;
}
void Undo( int levels )
{
cout<<"------ Undo "<<levels<<" levels"<<endl;
for( int i = 0; i < levels ; i++ )
{
if( _current > 0 )
{
int num = 0;
list<Command*>::iterator it = _commands.begin();
for( ; it != _commands.end() ;it++)
{
num++;
if( num == _current )
{
Command* com = *it;
com->UnExecute();
_current--;
}
}
}
}
}
void Redo( int levels )
{
cout<<"------ Redo "<<levels<<" levels"<<endl;
for( int i = 0 ; i < levels ; i++ )
{
if( _current < _commands.size() - 1 )
{
int num = 0;
list<Command*>::iterator it = _commands.begin();
for( ; it != _commands.end() ;it++)
{
if( num == _current )
{
Command* com = *it;
com->Execute();
_current++;
}
num++;
}
}
}
}
private:
Calculator* _calculator;
list<Command*> _commands;
int _current ;
};
class CommandExample1
{
public:
CommandExample1(void);
~CommandExample1(void);
void Start()
{
User* user = new User();
user->Compute('+' , 100);
user->Compute('-' , 50);
user->Compute('*' , 10);
user->Compute('/' , 2);
user->Undo(4);
user->Redo(3);
}
};