命令模式,最常应用的场景或许就是各种触发命令的场合。这个通过名称就可以联想,而且还比较容易理解。
而其他诸如回调啊之类的应用场景目前还不是很能体会。
命令模式目的用命令类本身将client和其真正实现者(receiver)进行解耦,从而用户只关心具体的命令,而不去关心其实现。而增加命令,对于现有的receiver和client都可以透明。
而对于命令中的可撤销等感觉也不是必须的。增加这个特性,可能只是为了支持事务等更规范一些。
写了个简单demo。每个命令都可以cancel,而如restart命令,可以认为是后加的。当然新命令,也可以对应新receiver。
/**
* @file command_test.cpp
* @author itegel
* @date 2013/05/27 19:02:26
* @brief
*
**/
#include <iostream>
using namespace std;
//receiver
class TV{
public:
TV(){
channel = 0;
}
~TV(){}
void TurnOn(){
cout<<"The TV is on!"<<endl;
}
void TurnOff(){
cout<<"The TV is off!"<<endl;
}
void IncreaseChannel(){
channel++;
cout<<"channel increased:"<<channel<<endl;
}
void DecreaseChannel(){
channel--;
cout<<"channel decreased:"<<channel<<endl;
}
private:
int channel;
};
class Command{
public:
Command(){}
~Command(){}
virtual void Execute() = 0;
virtual void UnExecute() = 0;
};
class TurnOnCmd : public Command{
public:
TurnOnCmd(TV * tv):_tv(tv){}
~TurnOnCmd(){}
virtual void Execute(){
_tv->TurnOn();
}
virtual void UnExecute(){
_tv->TurnOff();
}
private:
TV * _tv;
};
class TurnOffCmd : public Command{
public:
TurnOffCmd(TV * tv):_tv(tv){}
~TurnOffCmd(){}
virtual void Execute(){
_tv->TurnOff();
}
virtual void UnExecute(){
_tv->TurnOn();
}
private:
TV * _tv;
};
class IncreaseCmd : public Command{
public:
IncreaseCmd(TV * tv):_tv(tv){}
~IncreaseCmd(){}
virtual void Execute(){
_tv->IncreaseChannel();
}
virtual void UnExecute(){
_tv->DecreaseChannel();
}
private:
TV * _tv;
};
class RestartCmd : public Command{
public:
RestartCmd(TV * tv):_tv(tv){}
~RestartCmd(){}
virtual void Execute(){
_tv->TurnOff();
_tv->TurnOn();
}
virtual void UnExecute(){
cout<<"do nothing for Restart UnExecute!"<<endl;
}
private:
TV * _tv;
};
//client + invoker, user or remote controler
int main(){
TV * tv = new TV();
cout<<"Turn on command!"<<endl;
cout <<"Execute:"<<endl;
TurnOnCmd * turn_on = new TurnOnCmd(tv);
turn_on->Execute();
cout <<"Un Execute:"<<endl;
turn_on->UnExecute();
cout<<endl;
TurnOffCmd * turn_off = new TurnOffCmd(tv);
cout<<"trun off command!"<<endl;
cout<<"execute:"<<endl;
turn_off->Execute();
cout<<endl;
IncreaseCmd * increase = new IncreaseCmd(tv);
cout<<"increase command!"<<endl;
cout<<"execute1:"<<endl;
increase->Execute();
cout<<"execute 2:"<<endl;
increase->Execute();
cout<<"unexecute:"<<endl;
increase->UnExecute();
cout<<endl;
RestartCmd * restart = new RestartCmd(tv);
cout << "restart command!"<<endl;
cout<< "execute:"<<endl;
restart->Execute();
cout<< "un execute:"<<endl;
restart->UnExecute();
cout<<endl;
return 0;
}
执行结果:
Turn on command!
Execute:
The TV is on!
Un Execute:
The TV is off!
trun off command!
execute:
The TV is off!
increase command!
execute1:
channel increased:1
execute 2:
channel increased:2
unexecute:
channel decreased:1
restart command!
execute:
The TV is off!
The TV is on!
un execute:
do nothing for Restart UnExecute!
这里没有实现invoker。实际上加一个invoker,可以更好的隔离command和用户。而一个invoker可以是一个command组合。多个command也可以通过职责链等方式进行链接起来。
命令可以有自己的命令号,客户只知道命令号,而不去关心具体哪个具体命令类执行该命令,更不会关注receiver是怎么实现该命令的。