一、含义
命令模式(Command Pattern):将一个请求封装为一个对象,从而使我们可以用不同的请求对客户进行参数化,对请求排队或者记录请求日志,以及支持可撤销的操作。命令模式是一种对象行为型模式。
UML图如下所示:
二、结构
抽象命令(Command):一般定义为接口,用来定义执行命令的接口。
具体命令(ConcreteCommand):通常会持有接收者对象,并调用接收者对象的相应功能来完成命令要执行的操作。
接收者(Receiver):真正执行命令的对象。任何类都可能成为接收者,只要能够实现命令要求实现的相应功能。
调用者(Invoker):要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象。
客户端(Client):创建具体的命令对象,并且设置命令对象的接收者。
三、优缺点
优点:
1、降低对象间的耦合度;
2、扩展性,新的命令可以很容易加入到系统中;
3、组合命令,很容易组成复合命令;
4、动态控制,参数化、队列化、批处理、Undo/Redo操作;
缺点:
使用命令模式可能会导致某些系统有过多的命令类。
四、适用情况
对于大多数请求-响应模式的功能,比较适合使用命令模式。例如实现记录日志、操作撤销等功能比较方便。
五、应用
1、JAVA
1.1 通用模板
// 命令接收者:具体执行命令
class Receiver{
public void doSomething(){
System.out.println("Receiver: Do something!");
}
}
// 执行命令的接口
abstract class Command{
public abstract void execute();
}
// 具体命令
class ConcreteCommand extends Command{
private Receiver receiver;
public ConcreteCommand(Receiver receiver){
this.receiver = receiver;
}
public void execute(){
this.receiver.doSomething();
}
}
// 调用者
class Invoker{
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void action(){
this.command.execute();
}
}
// 客户端
class Client{
public Client(){
}
public void doWork() {
Receiver receiver = new Receiver();
Command command = new ConcreteCommand(receiver);
Invoker invoker = new Invoker();
invoker.setCommand(command);
invoker.action();
}
}
1.2 开灯关灯命令例子
class LightReciver{
private boolean isOn = false;
public boolean isOn(){
return isOn;
}
public void turnOn() {
isOn = true;
}
public void turnOff(){
isOn = false;
}
}
interface Command{
void excute();
void undo();
}
class LightOnCommand implements Command{
private LightReciver light;
private boolean lastState;
public LightOnCommand(LightReciver light){
this.light = light;
}
@Override
public void excute() {
lastState = this.light.isOn();
this.light.turnOn();
}
@Override
public void undo() {
if(lastState){
this.light.turnOn();
}
else{
this.light.turnOff();
}
}
}
class ControlInvoker{
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressTurnOn(){
this.command.excute();
}
public void pressUndo(){
this.command.undo();
}
}
class Client{
public Client(){}
public void doWork(){
// 指定Receiver
LightReciver reciver = new LightReciver();
// 创建具体命令对象
Command command = new LightOnCommand(reciver);
// 创建调用者对象,并设置命令对象
ControlInvoker control = new ControlInvoker();
control.setCommand(command);
// 执行命令
control.pressTurnOn();
control.pressUndo();
}
}
2、C++
2.1 通用模板
// 接收者
// .h
class Receiver
{
public:
void doSomeThing();
};
// .cpp
void Receiver::doSomeThing()
{
printf("hard working\n");
}
// 接口命令类
class Command
{
public:
virtual void excute() = 0;
};
// 具体命令
// .h
class ConcreteCommand : public Command
{
public:
ConcreteCommand(Receiver reciver);
void excute();
private:
Receiver reciver;
};
// .cpp
ConcreteCommand::ConcreteCommand(Receiver reciverIn)
{
reciver = reciverIn;
}
void ConcreteCommand::excute()
{
reciver.doSomeThing();
}
// 调用者
// .h
class Invoker {
public:
Invoker();
void setCommand(ConcreteCommand* cmd);
void action();
private:
ConcreteCommand* invokerCmd;
};
// .cpp
Invoker::Invoker()
{
}
void Invoker::setCommand(ConcreteCommand* cmd)
{
invokerCmd = cmd;
}
void Invoker::action()
{
invokerCmd->excute();
}
// 客户端
// .h
class Client {
public:
void doWork();
};
// .cpp
void Client::doWork()
{
Receiver reciver;
ConcreteCommand* cmd = new ConcreteCommand(reciver);
Invoker invoker;
invoker.setCommand(cmd);
invoker.action();
}
2.2 开灯关灯命令例子
// 接收者
// .h
class LightReceiver
{
public:
bool isLightOn();
void turnOn();
void turnOff();
private:
bool isOn = 0;
};
// .cpp
bool LightReceiver::isLightOn()
{
return isOn;
}
void LightReceiver::turnOn()
{
isOn = true;
printf("Light On!\n");
}
void LightReceiver::turnOff()
{
isOn = false;
}
// 接口命令类
class Command
{
public:
virtual void excute() = 0;
virtual void undo() = 0;
};
// 具体命令
// .h
class LightOnCommand : public Command
{
public:
LightOnCommand(LightReceiver reciver);
void excute();
void undo();
private:
LightReceiver m_reciver;
bool lastState;
};
// .cpp
LightOnCommand::LightOnCommand(LightReceiver reciver)
{
m_reciver = reciver;
}
void LightOnCommand::excute()
{
lastState = m_reciver.isLightOn();
m_reciver.turnOn();
}
void LightOnCommand::undo()
{
if (lastState) {
m_reciver.turnOn();
printf("Undo, Current Status:ON\n");
}
else {
m_reciver.turnOff();
printf("Undo, Current Status:OFF\n");
}
}
// 调用者
// .h
class Invoker {
public:
Invoker();
void setCommand(LightOnCommand* cmd);
void pressTurnOn();
void pressUndo();
private:
LightOnCommand* invokerCmd;
};
// .cpp
Invoker::Invoker()
{
}
void Invoker::setCommand(LightOnCommand* cmd)
{
invokerCmd = cmd;
}
void Invoker::pressTurnOn()
{
invokerCmd->excute();
}
void Invoker::pressUndo()
{
invokerCmd->undo();
}
// 客户端
// .h
class Client {
public:
void doWork();
};
// .cpp
void Client::doWork()
{
LightReceiver reciver;
LightOnCommand* cmd = new LightOnCommand(reciver);
Invoker invoker;
invoker.setCommand(cmd);
invoker.pressTurnOn();
invoker.pressUndo();
}