1. 命令模式:让代码像将军指挥士兵一样优雅
作为一名在Java领域摸爬滚打多年的老码农,我见过太多因为设计混乱而难以维护的代码库。今天要聊的命令模式,就像军队里的指挥系统——将军(调用者)不需要知道每个士兵(接收者)的具体作战细节,只需要发布命令(Command对象)就能让整个系统有序运转。这种将"做什么"和"怎么做"解耦的思想,正是优秀软件设计的精髓所在。
命令模式属于行为型设计模式,核心在于把请求封装成独立的对象。想象你正在开发一个智能家居系统:点击手机APP上的"回家模式"按钮,系统需要依次执行开灯、开空调、播放音乐等操作。如果把这些操作直接硬编码在按钮点击事件里,后续要新增操作就得修改按钮代码——这明显违反了开闭原则。而命令模式通过将每个操作封装成命令对象,完美解决了这个问题。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 命令模式的核心架构解析
2.1 类图深度解读
先来看命令模式的经典类图结构(虽然不能放图,但可以用文字精准描述):
- Command接口:定义执行操作的统一方法(通常就是execute()),这是所有具体命令的契约
- ConcreteCommand:实现Command接口的具体命令类(如开灯命令),内部会持有接收者引用
- Invoker:命令的调用者/触发器(如遥控器按钮),它只知道调用命令的execute(),不关心具体实现
- Receiver:实际执行业务逻辑的对象(如电灯),但命令对象会调用它的方法
这种结构的美妙之处在于:Invoker完全不知道Receiver的存在,它只和Command接口耦合。就像你按遥控器时,不需要知道电视内部如何工作。
2.2 代码实现剖析
让我们用Java代码还原这个模式。假设我们要实现文本编辑器的撤销功能:
java复制// 命令接口
public interface Command {
void execute();
void undo(); // 新增撤销功能
}
// 具体命令:插入文本
public class InsertCommand implements Command {
private StringBuilder receiver;
private String text;
private int position;
public InsertCommand(StringBuilder sb, String text, int pos) {
this.receiver = sb;
this.text = text;
this.position = pos;
}
@Override
public void execute() {
receiver.insert(position, text);
}
@Override
public void undo() {
receiver.delete(position, position + text.length());
}
}
// 调用者:菜单项
public class MenuItem {
private Command command;
public void setCommand(Command cmd) {
this.command = cmd;
}
public void click() {
command.execute();
// 将命令存入历史列表,用于撤销
CommandHistory.push(command);
}
}
关键技巧:命令对象应该尽可能轻量。如果Receiver很大,可以考虑在命令中只保存必要参数,执行时再从服务定位器获取Receiver。
