命令模式 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);
}
};