1、 定义
1.1 标准定义
命令模式是一个高内聚的模式,其定义为:
Encapsulate a request as an object,therebyletting you parameterize clients with different requests,queue or log requests,and support undoableoperations.(将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。)
1.2 类图
● Receive接收者角色
该角色就是干活的角色, 命令传递到这里是应该被执行的。● Command命令角色
需要执行的所有命令都在这里声明。● Invoker调用者角色
接收到命令, 并执行命令。2、实现
2.1 类图
Command类,用来声明执行操作的接口;
ConcreteCommand,将一个接收者对象绑定于一个操作,调用接收者相应的操作,以实现Execute;
Invoker类,要求该命令执行这个请求;
Receiver类,知道如何实施与执行一个与请求相关的操作,任何类都可能作为一个接收者。
Command模式通过将请求封装到一个对象Command中,并将请求的接收者存放到具体的ConcreteCommand类中,从而实现调用操作的对象和操作的具体实现者之间的解耦。
Command模式结构图中,将请求的接收者(处理者)放到Command的具体子类ConcreteCommand中,当请求到来时(Invoker发出Invoke消息激活Command对象),ConcreteCommand将处理请求交给Receiver对象进行处理。
2.2 代码
2.2.1 command类
// Command.h#ifndef _COMMAND_H_#define _COMMAND_H_class Command{public: virtual ~Command(); virtual void Execute()=0;protected: Command();private:};class Receiver;class ConcreteCommand : public Command{public: ConcreteCommand(Receiver* pReceiver); ~ConcreteCommand(); virtual void Execute();protected:private: Receiver* _recv;};class Invoker{public: Invoker(Command* pCommand); ~Invoker(); void Invoke();protected:private: Command* _cmd;};class Receiver{public: Receiver(); ~Receiver(); void Action();protected:private:};#endif
// Command.cpp#include "Command.h"#includeusing namespace std;Command::Command(){}Command::~Command(){}ConcreteCommand::ConcreteCommand(Receiver* pReceiver){ this->_recv = pReceiver;}ConcreteCommand::~ConcreteCommand(){}void ConcreteCommand::Execute(){ this->_recv->Action();}Receiver::Receiver(){}Receiver::~Receiver(){}void Receiver::Action(){ cout << "Receiver::Action" << endl;}Invoker::Invoker(Command* pCommand){ this->_cmd = pCommand;}Invoker::~Invoker(){}void Invoker::Invoke(){ this->_cmd->Execute();}
2.2.2 调用
// main.cpp#include "Command.h"int main(){ //创建具体命令对象pCmd并设定它的接收者pRev Receiver* pRev = new Receiver(); Command* pCmd = new ConcreteCommand(pRev); //请求绑定命令 Invoker* pInv = new Invoker(pCmd); pInv->Invoke(); return 0;}
3、优缺点
3.1 优点
● 类间解耦
调用者角色与接收者角色之间没有任何依赖关系, 调用者实现功能时只需调用Command抽象类的execute方法就可以, 不需要了解到底是哪个接收者执行。● 可扩展性
Command的子类可以非常容易地扩展, 而调用者Invoker和高层次的模块Client不产生严重的代码耦合。● 命令模式结合其他模式会更优秀
命令模式可以结合责任链模式, 实现命令族解析任务; 结合模板方法模式, 则可以减少Command子类的膨胀问题。● 可操作性
允许接收请求的一方决定是否要否决请求;可以容易地实现对请求的撤销和重做。3.2 缺点
命令模式也是有缺点的,请看Command的子类:如果有N个命令,问题就出来了,Command的子类就可不是几个,而是N个,这个类膨胀得非常大,这个就需要在项目中慎重考虑使用。