在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,我们只需在程序运行时指定具体的请求接收者即可,此时,可以使用命令模式来进行设计,使得请求发送者与请求接收者消除彼此之间的耦合,让对象之间的调用关系更加灵活。
命令模式可以对发送者和接收者完全解耦,发送者与接收者之间没有直接引用关系,发送请求的对象只需要知道如何发送请求,而不必知道如何完成请求。这就是命令模式的模式动机。
命令模式(Command Pattern):将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。命令模式是一种对象行为型模式,其别名为动作(Action)模式或事务(Transaction)模式。
命令模式包含如下角色:
#include <iostream> #include "ConcreteCommand.h" #include "Invoker.h" #include "Receiver.h" using namespace std; int main(int argc, char *argv[]) { Receiver * pReceiver = new Receiver(); ConcreteCommand * pCommand = new ConcreteCommand(pReceiver); Invoker * pInvoker = new Invoker(pCommand); pInvoker->call(); delete pReceiver; delete pCommand; delete pInvoker; return 0; }
/////////////////////////////////////////////////////////// // Receiver.h // Implementation of the Class Receiver // Created on: 07-十月-2014 17:44:02 // Original author: colin /////////////////////////////////////////////////////////// #if !defined(EA_8E5430BB_0904_4a7d_9A3B_7169586237C8__INCLUDED_) #define EA_8E5430BB_0904_4a7d_9A3B_7169586237C8__INCLUDED_ class Receiver { public: Receiver(); virtual ~Receiver(); void action(); }; #endif // !defined(EA_8E5430BB_0904_4a7d_9A3B_7169586237C8__INCLUDED_)
/////////////////////////////////////////////////////////// // Receiver.cpp // Implementation of the Class Receiver // Created on: 07-十月-2014 17:44:02 // Original author: colin /////////////////////////////////////////////////////////// #include "Receiver.h" #include <iostream> using namespace std; Receiver::Receiver(){ } Receiver::~Receiver(){ } void Receiver::action(){ cout << "receiver action." << endl; }
/////////////////////////////////////////////////////////// // ConcreteCommand.h // Implementation of the Class ConcreteCommand // Created on: 07-十月-2014 17:44:01 // Original author: colin /////////////////////////////////////////////////////////// #if !defined(EA_1AE70D53_4868_4e81_A1B8_1088DA355C23__INCLUDED_) #define EA_1AE70D53_4868_4e81_A1B8_1088DA355C23__INCLUDED_ #include "Command.h" #include "Receiver.h" class ConcreteCommand : public Command { public: ConcreteCommand(Receiver * pReceiver); virtual ~ConcreteCommand(); virtual void execute(); private: Receiver *m_pReceiver; }; #endif // !defined(EA_1AE70D53_4868_4e81_A1B8_1088DA355C23__INCLUDED_)
/////////////////////////////////////////////////////////// // ConcreteCommand.cpp // Implementation of the Class ConcreteCommand // Created on: 07-十月-2014 17:44:02 // Original author: colin /////////////////////////////////////////////////////////// #include "ConcreteCommand.h" #include <iostream> using namespace std; ConcreteCommand::ConcreteCommand(Receiver *pReceiver){ m_pReceiver = pReceiver; } ConcreteCommand::~ConcreteCommand(){ } void ConcreteCommand::execute(){ cout << "ConcreteCommand::execute" << endl; m_pReceiver->action(); }
/////////////////////////////////////////////////////////// // Invoker.h // Implementation of the Class Invoker // Created on: 07-十月-2014 17:44:02 // Original author: colin /////////////////////////////////////////////////////////// #if !defined(EA_3DACB62A_0813_4d11_8A82_10BF1FB00D9A__INCLUDED_) #define EA_3DACB62A_0813_4d11_8A82_10BF1FB00D9A__INCLUDED_ #include "Command.h" class Invoker { public: Invoker(Command * pCommand); virtual ~Invoker(); void call(); private: Command *m_pCommand; }; #endif // !defined(EA_3DACB62A_0813_4d11_8A82_10BF1FB00D9A__INCLUDED_)
/////////////////////////////////////////////////////////// // Invoker.cpp // Implementation of the Class Invoker // Created on: 07-十月-2014 17:44:02 // Original author: colin /////////////////////////////////////////////////////////// #include "Invoker.h" #include <iostream> using namespace std; Invoker::Invoker(Command * pCommand){ m_pCommand = pCommand; } Invoker::~Invoker(){ } void Invoker::call(){ cout << "invoker calling" << endl; m_pCommand->execute(); }
运行结果:
命令模式的本质是对命令进行封装,将发出命令的责任和执行命令的责任分割开。
实例一:电视机遥控器
时序图:
命令模式的优点
命令模式的缺点
在以下情况下可以使用命令模式:
很多系统都提供了宏命令功能,如UNIX平台下的Shell编程,可以将多条命令封装在一个命令对象中,只需要一条简单的命令即可执行一个命令序列,这也是命令模式的应用实例之一。
宏命令又称为组合命令,它是命令模式和组合模式联用的产物。
-宏命令也是一个具体命令,不过它包含了对其他命令对象的引用,在调用宏命令的execute()方法时,将递归调用它所包含的每个成员命令的execute()方法,一个宏命令的成员对象可以是简单命令,还可以继续是宏命令。执行一个宏命令将执行多个具体命令,从而实现对命令的批处理。
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8