命令(Command)模式定义
命令模式(Command),将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
命令(Command)模式优缺点
优点
- 它能较容易的设计一个命令队列;
- 在需要的情况下,可以较容易的将命令计入日志;
- 允许接收请求的一方决定是否要否决请求;
- 可以容易的实现对请求的撤销和重做;
- 由于加进新的具体命令类不影响其他的类,因此增加新的具体命令类很容易;
- 把请求一个操作的对象与知道怎么执行一个操作的对象分隔开;
缺点
- 代码可能会变得更加复杂,因为你在发送者和接收者之间增 加了一个全新的层次
命令(Command)模式构成与实现
构成
- 发送者(Sender)——亦称“触发者(Invoker)”——类负责对请求进行初始化,其中必须包含一个成员变量来存储对于命令对象的引用。发送者触发命令,而不向接收者直接发送请求。注意,发送者并不负责创建命令对象:它通常会通过构造函数从客户端处获得预先生成的命令。
- 命令(Command)接口通常仅声明一个执行命令的方法。
- 具体命令(Concrete Commands)会实现各种类型的请求。具体命令自身并不完成工作,而是会将调用委派给一个业务逻辑对象。但为了简化代码,这些类可以进行合并。接收对象执行方法所需的参数可以声明为具体命令的成员变量。你可以将命令对象设为不可变,仅允许通过构造函数对这些成员变量进行初始化。
- 接收者(Receiver)类包含部分业务逻辑。几乎任何对象都可以作为接收者。绝大部分命令只处理如何将请求传递到接收者的细节,接收者自己会完成实际的工作。
- 客户端(Client)会创建并配置具体命令对象。客户端必须将包括接收者实体在内的所有请求参数传递给命令的构造函数。此后,生成的命令就可以与一个或多个发送者相关联了。
实例
Command.h:
#ifndef COMMAND_H_
#define COMMAND_H_
// 命令接口, C++中为抽象基类
class Command {
public:
virtual void execute() = 0;
};
#endif // COMMAND_H_
Receiver.h:
#ifndef RECEIVER_H_
#define RECEIVER_H_
#include <iostream>
// 接受者: 电视
class Television{
public:
void open() {
std::cout << "打开电视机!" << std::endl;
}
void close() {
std::cout << "关闭电视机!" << std::endl;
}
void changeChannel(){
std::cout << "切换电视频道!" << std::endl;
}
};
#endif // RECEIVER_H_
ConcreteCommand.h:
#ifndef CONCRETE_COMMAND_H_
#define CONCRETE_COMMAND_H_
#include <memory>
#include "Command.h"
#include "Receiver.h"
// 具体命令类: 打开电视
class TVOpenCommand : public Command{
public:
explicit TVOpenCommand(std::shared_ptr<Television> tv) : tv_(tv) {}
void execute() {
tv_->open();
}
private:
std::shared_ptr<Television> tv_;
};
// 具体命令类: 关闭电视
class TVCloseCommand : public Command{
public:
explicit TVCloseCommand(std::shared_ptr<Television> tv) : tv_(tv) {}
void execute() {
tv_->close();
}
private:
std::shared_ptr<Television> tv_;
};
// 具体命令类: 切换频道
class TVChangeCommand : public Command{
public:
explicit TVChangeCommand(std::shared_ptr<Television> tv) : tv_(tv) {}
void execute() {
tv_->changeChannel();
}
private:
std::shared_ptr<Television> tv_;
};
#endif // CONCRETE_COMMAND_H_
Invoker.h:
#ifndef INVOKER_H_
#define INVOKER_H_
#include <memory>
#include "Command.h"
// 触发者: 遥控器
class Controller{
public:
Controller() {}
// 设置命令
void setCommand(std::shared_ptr<Command> cmd) {
cmd_ = cmd;
}
// 执行命令
void executeCommand() {
cmd_->execute();
}
private:
std::shared_ptr<Command> cmd_;
};
#endif // INVOKER_H_
main.cpp:
#include "Invoker.h"
#include "ConcreteCommand.h"
int main() {
system("chcp 65001");
// 接收者: 电视机
std::shared_ptr<Television> tv = std::make_shared<Television>();
// 命令
std::shared_ptr<Command> openCommand = std::make_shared<TVOpenCommand>(tv);
std::shared_ptr<Command> closeCommand = std::make_shared<TVCloseCommand>(tv);
std::shared_ptr<Command> changeCommand = std::make_shared<TVChangeCommand>(tv);
// 调用者: 遥控器
std::shared_ptr<Controller> controller = std::make_shared<Controller>();
// 测试
controller->setCommand(openCommand);
controller->executeCommand();
controller->setCommand(closeCommand);
controller->executeCommand();
controller->setCommand(changeCommand);
controller->executeCommand();
system("pause");
}
输出:
Active code page: 65001
打开电视机!
关闭电视机!
切换电视频道!
Press any key to continue . . .