【设计模式】【行为型模式(Behavioral Patterns)】之命令模式(Command Pattern)
1. 设计模式原理说明
命令模式(Command Pattern) 是一种行为设计模式,它将请求封装成对象,从而使你可以用不同的请求对客户进行参数化、队列请求或将请求日志化,同时支持可撤销的操作。通过这种方式,可以将请求发送者与接收者解耦,使得两者之间不再直接联系,而是通过命令对象进行交互。
主要角色
- Command(命令接口):声明执行操作的接口。
- ConcreteCommand(具体命令):将接收者对象与动作绑定,调用接收者相应的操作,实现Command接口。
- Receiver(接收者):知道如何实施与执行一个请求相关的操作。任何类都可能作为一个接收者。
- Invoker(调用者):要求该命令执行这个请求,它依赖于Command。
- Client(客户端):创建具体的命令对象,并设置其接收者。
2. UML 类图及解释
UML 类图
+-----------------+ +-----------------+
| Command | | Receiver |
|-----------------| |-----------------|
| - execute() | | - action() |
+-----------------+ +-----------------+
^ ^
| |
| |
v v
+-----------------+ +-----------------+
| ConcreteCommand | | ConcreteReceiver|
|-----------------| |-----------------|
| - receiver: Receiver | | - action() |
| - execute() | +-----------------+
+-----------------+
^
|
|
v
+-----------------+
| Invoker |
|-----------------|
| - command: Command |
| - setCommand(command: Command) |
| - executeCommand() |
+-----------------+
类图解释
- Command:定义了执行操作的接口。
- ConcreteCommand:实现了Command接口,将接收者对象与动作绑定。
- Receiver:执行具体的操作,可以是任何类。
- Invoker:负责调用命令对象的execute方法,但不关心具体执行什么操作。
- Client:创建命令对象并设置接收者,然后将命令对象传递给调用者。
3. 代码案例及逻辑详解
Java 代码案例
// 命令接口
interface Command {
void execute();
}
// 接收者
class Receiver {
public void action() {
System.out.println("Executing action");
}
}
// 具体命令
class ConcreteCommand implements Command {
private Receiver receiver;
public ConcreteCommand(Receiver receiver) {
this.receiver = receiver;
}
@Override
public void execute() {
receiver.action();
}
}
// 调用者
class Invoker {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void executeCommand() {
if (command != null) {
command.execute();
}
}
}
// 客户端
public class Client {
public static void main(String[] args) {
Receiver receiver = new Receiver();
Command command = new ConcreteCommand(receiver);
Invoker invoker = new Invoker();
invoker.setCommand(command);
invoker.executeCommand();
}
}
C++ 代码案例
#include <iostream>
// 命令接口
class Command {
public:
virtual ~Command() {}
virtual void execute() = 0;
};
// 接收者
class Receiver {
public:
void action() {
std::cout << "Executing action" << std::endl;
}
};
// 具体命令
class ConcreteCommand : public Command {
private:
Receiver* receiver;
public:
ConcreteCommand(Receiver* receiver) : receiver(receiver) {}
void execute() override {
receiver->action();
}
};
// 调用者
class Invoker {
private:
Command* command;
public:
void setCommand(Command* command) {
this->command = command;
}
void executeCommand() {
if (command != nullptr) {
command->execute();
}
}
};
// 客户端
int main() {
Receiver receiver;
Command* command = new ConcreteCommand(&receiver);
Invoker invoker;
invoker.setCommand(command);
invoker.executeCommand();
delete command;
return 0;
}
Python 代码案例
# 命令接口
class Command:
def execute(self):
raise NotImplementedError
# 接收者
class Receiver:
def action(self):
print("Executing action")
# 具体命令
class ConcreteCommand(Command):
def __init__(self, receiver):
self.receiver = receiver
def execute(self):
self.receiver.action()
# 调用者
class Invoker:
def __init__(self):
self.command = None
def set_command(self, command):
self.command = command
def execute_command(self):
if self.command:
self.command.execute()
# 客户端
if __name__ == "__main__":
receiver = Receiver()
command = ConcreteCommand(receiver)
invoker = Invoker()
invoker.set_command(command)
invoker.execute_command()
Go 代码案例
package main
import (
"fmt"
)
// 命令接口
type Command interface {
execute()
}
// 接收者
type Receiver struct{}
func (r *Receiver) action() {
fmt.Println("Executing action")
}
// 具体命令
type ConcreteCommand struct {
receiver *Receiver
}
func (c *ConcreteCommand) execute() {
c.receiver.action()
}
// 调用者
type Invoker struct {
command Command
}
func (i *Invoker) setCommand(command Command) {
i.command = command
}
func (i *Invoker) executeCommand() {
if i.command != nil {
i.command.execute()
}
}
// 客户端
func main() {
receiver := &Receiver{}
command := &ConcreteCommand{receiver: receiver}
invoker := &Invoker{}
invoker.setCommand(command)
invoker.executeCommand()
}
4. 总结
命令模式 是一种行为设计模式,它将请求封装成对象,从而使你可以用不同的请求对客户进行参数化、队列请求或将请求日志化,同时支持可撤销的操作。通过这种方式,可以将请求发送者与接收者解耦,使得两者之间不再直接联系,而是通过命令对象进行交互。
主要优点
- 解耦:命令模式将请求的发送者和接收者解耦,使得两者之间不再直接联系。
- 扩展性:新增命令时,只需添加新的具体命令类,无需修改现有代码,符合开闭原则。
- 支持撤销操作:命令对象可以保存状态,从而支持撤销和重做操作。
- 支持队列请求:可以将命令对象放入队列中,实现异步处理。
主要缺点
- 增加系统复杂度:引入命令模式会增加系统的复杂度,因为需要额外的命令类和调用者类。
- 性能开销:命令模式可能会带来一些性能开销,特别是在命令对象较多时。
适用场景
- 当需要将请求排队或记录请求日志,或者支持可撤销操作时。
- 当需要参数化对象来指定要执行的操作时。
- 当需要在不同的时刻指定、排列和执行请求时。
- 当需要将请求发送者与接收者解耦时。