命令模式:解耦请求与执行的优雅之道
引言:软件设计的解耦艺术
在软件开发中,我们常面临请求发起者与请求执行者之间的紧密耦合问题。这种耦合会导致:
- 系统扩展困难:新增命令需要修改现有代码
- 功能复用受限:相同操作无法在不同上下文中重用
- 撤销/重做复杂:操作历史难以追踪和管理
命令模式正是为解决这类问题而生的设计模式。它将请求封装成独立对象,允许你参数化客户端使用不同的请求、队列或日志请求,并支持可撤销的操作。本文将深入解析命令模式的原理、实现及高级应用场景。
一、模式定义与核心思想
1.1 官方定义
命令模式 (Command Pattern):将请求封装成对象,从而让你使用不同的请求、队列或日志请求来参数化其他对象,并支持可撤销的操作。
1.2 设计哲学
核心原则:
- 解耦调用与执行:调用者无需知道接收者细节
- 命令对象化:将操作封装为可传递的对象
- 支持扩展:新增命令不影响现有系统结构
二、模式结构解析
2.1 UML类图
classDiagramclass Invoker {-command: Command+setCommand(Command)+executeCommand()}interface Command {<<interface>>+execute()+undo()}class ConcreteCommand {-receiver: Receiver-state+execute()+undo()}class Receiver {+action()}Invoker o--> CommandCommand <|.. ConcreteCommandConcreteCommand --> Receiver
2.2 关键角色
角色 | 职责 | 示例 |
---|---|---|
Invoker | 触发命令执行 | 遥控器按钮 |
Command | 声明执行接口 | 命令接口 |
ConcreteCommand | 实现具体命令 | 开灯命令 |
Receiver | 实际执行操作 | 电灯设备 |
三、代码实战:智能家居控制系统
3.1 场景描述
实现智能家居控制系统:
- 控制多种设备:灯、空调、音响
- 支持单命令执行和宏命令(组合命令)
- 实现撤销操作功能
3.2 核心实现
// 命令接口
public interface Command {void execute();void undo();
}// 接收者:电灯
public class Light {public void on() {System.out.println("电灯已打开");}public void off() {System.out.println("电灯已关闭");}
}// 具体命令:开灯命令
public class LightOnCommand implements Command {private final Light light;public LightOnCommand(Light light) {this.light = light;}@Overridepublic void execute() {light.on();}@Overridepublic void undo() {light.off();}
}// 接收者:空调
public class AirConditioner {private int temperature = 26;public void setTemperature(int temp) {this.temperature = temp;System.out.println("空调温度设置为: " + temp + "℃");}public int getTemperature() {return temperature;}
}// 具体命令:设置空调温度
public class SetTemperatureCommand implements Command {private final AirConditioner ac;private final int newTemperature;private int prevTemperature;public SetTemperatureCommand(AirConditioner ac, int temperature) {this.ac = ac;this.newTemperature = temperature;}@Overridepublic void execute() {prevTemperature = ac.getTemperature();ac.setTemperature(newTemperature);}@Overridepublic void undo</