命令模式(Command Pattern)
- 命令模式(Command Pattern)
- 命令设计模式
- 命令设计模式结构图
- 命令设计模式涉及的角色
- talk is cheap, show you my code
- 总结
命令模式(Command Pattern)
命令模式(Command Pattern)是一种行为型设计模式,它将请求封装为对象,从而使你可以用不同的请求对客户进行参数化、队列或者日志请求,以及支持可撤销的操作。命令模式的核心思想是将“请求”作为一个对象来处理,将发出请求的责任和执行请求的责任分割开。
太抽象了,我们还是举个现实中的例子
假如你现在在装修家,你很有可能要买一个开关。但是我们这个开关不一定是用来开关灯的,也有可能是用来控制别的东西,所以这个开关不一定是跟灯是关联的。我们的开关你可以当成我们面向对象设计里面的一个对象,它不跟灯有直接的耦合关系。开关相当于发送者,开关与什么用电器关联,开关就控制哪一个用电器。实际上你可以这样理解命令模式,通过使用命令模式,我们隔离发送请求的与执行请求的对象。
命令设计模式
命令设计模式结构图
命令设计模式涉及的角色
- 命令接口(Command):声明了所有具体命令必须实现的方法
public interface Command {
void execute();
void undo(); // 可选,用于撤销操作
}
- 具体命令(ConcreteCommand):实现了Command接口的具体类。每个具体命令都包含对一个接收者的引用,并负责调用接收者的方法来执行实际的操作。
public class ConcreteCommand implements Command {
private final Receiver receiver;
public ConcreteCommand(Receiver receiver) {
this.receiver = receiver;
}
@Override
public void execute() {
receiver.performAction();
}
@Override
public void undo() {
receiver.undoAction(); // 假设接收者有撤销功能
}
}
- 接收者(Receiver):接收者知道如何执行与请求相关的操作。任何类都可以成为接收者,只要它提供了可以被命令对象调用的方法。
public class Receiver {
public void performAction() {
System.out.println("Executing action in Receiver");
}
public void undoAction() {
System.out.println("Undoing action in Receiver");
}
}
- 请求发送者(Invoker):请求发送者持有一个命令对象,并负责调用命令对象的execute()方法来触发请求。发送者不需要知道具体的接收者是谁,也不需要知道请求的具体内容。
public class Invoker {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void executeCommand() {
if (command != null) {
command.execute();
}
}
public void undoCommand() {
if (command != null) {
command.undo();
}
}
}
- 客户端(Client):客户端创建具体的命令对象,并将其与接收者关联起来。然后,客户端将命令对象传递给请求发送者,由发送者在适当的时候调用命令对象的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(); // 执行命令
invoker.undoCommand(); // 撤销命令
}
}
talk is cheap, show you my code
我们还是把我们举得例子转化成代码:
- 定义接收者(Receiver):首先,我们定义Light类,它包含打开和关闭灯光的方法。
public class Light {
public void on() {
System.out.println("The light is ON.");
}
public void off() {
System.out.println("The light is OFF.");
}
}
- 定义命令接口(Command Interface):接下来,我们定义一个命令接口Command,所有具体命令都必须实现这个接口。
public interface Command {
void execute();
}
- 实现具体命令(Concrete Commands)
public class LightOnCommand implements Command {
private final Light light;
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.on();
}
}
public class LightOffCommand implements Command {
private final Light light;
public LightOffCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.off();
}
}
- 定义请求发送者(Invoker)
现在,我们创建一个Switch类作为请求发送者。它持有一个命令对象,并负责调用命令对象的execute()方法。
public class Switch {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void press() {
if (command != null) {
command.execute();
} else {
System.out.println("No command set.");
}
}
}
- 客户端代码(Client)
public class Client {
public static void main(String[] args) {
// 创建接收者
Light light = new Light();
// 创建命令对象
Command lightOn = new LightOnCommand(light);
Command lightOff = new LightOffCommand(light);
// 创建请求发送者并设置命令
Switch switchButton = new Switch();
switchButton.setCommand(lightOn);
switchButton.press(); // 执行打开灯光命令
switchButton.setCommand(lightOff);
switchButton.press(); // 执行关闭灯光命令
}
}
最后,在客户端代码中,我们将创建一个Light实例,以及相应的LightOnCommand和LightOffCommand实例。然后,我们将这些命令设置到Switch对象中,并通过调用press()方法来触发命令的执行。
总结
命令模式的主要优点包括:
- 降低了系统的耦合度。
- 新的命令可以很容易地加入到系统中。
- 可以方便地实现对请求的撤销和重做。
不过,命令模式也可能增加系统的复杂性,因为它需要引入许多新的类。如果系统比较简单,使用命令模式可能会显得过于繁琐。