文章目录
- [命令模式(Command Pattern)](#命令模式(Command Pattern))
- 核心原理
- [Java 实践示例](#Java 实践示例)
- 运行结果
- 命令模式的核心价值
- [命令模式在 GUI 操作、事务管理、任务调度等场景中应用广泛,例如:](#命令模式在 GUI 操作、事务管理、任务调度等场景中应用广泛,例如:)
命令模式(Command Pattern)
命令模式是 23 种设计模式中的一种行为型模式,其核心思想是将请求封装为一个对象(命令),从而使你可以用不同的请求对客户进行参数化,并且支持请求的排队、记录日志、撤销等操作。
核心原理
命令接口(Command):
声明执行操作的方法(通常是execute())
可选地声明撤销操作的方法(undo())
具体命令(ConcreteCommand):
实现命令接口,持有接收者(Receiver)的引用
在execute()方法中调用接收者的具体操作
若支持撤销,需在undo()中实现反向操作
接收者(Receiver):
知道如何执行与请求相关的操作,是实际业务逻辑的执行者
与命令解耦,不关心命令的存在
调用者(Invoker):
持有命令对象,负责触发命令的执行
不关心命令的具体实现和接收者是谁
客户端(Client):
创建具体命令对象,并设置其接收者
决定哪个命令与哪个接收者关联
命令模式的核心是 "封装请求",将发出请求的责任和执行请求的责任分割开,通过命令对象连接两者。
Java 实践示例
下面以 "遥控器控制家电" 为例实现命令模式:
遥控器(调用者)可执行各种命令(开 / 关灯光、开 / 关电视)
支持命令的执行和撤销操作
bash
package com.example.demo;
public class CommandPattern {
public static void main(String[] args) {
// 创建接收者(家电)
Light livingRoomLight = new Light("客厅");
TV livingRoomTV = new TV("客厅");
// 创建命令
Command lightOn = new LightOnCommand(livingRoomLight);
Command lightOff = new LightOffCommand(livingRoomLight);
Command tvOn = new TVOnCommand(livingRoomTV);
Command tvOff = new TVOffCommand(livingRoomTV);
// 创建调用者(遥控器)
RemoteControl remote = new RemoteControl();
// 执行命令
System.out.println("--- 执行命令 ---");
remote.setCommand(lightOn);
remote.pressButton();
remote.setCommand(tvOn);
remote.pressButton();
// 撤销命令
System.out.println("\n--- 撤销命令 ---");
remote.pressUndoButton();
remote.pressUndoButton();
// 再次执行关闭命令
System.out.println("\n--- 执行关闭命令 ---");
remote.setCommand(lightOff);
remote.pressButton();
}
public interface Command {
void execute();
void undo();
}
// 灯光接收者
public static class Light {
private String location;
private boolean isOn;
public Light(String location) {
this.location = location;
}
public void on() {
isOn = true;
System.out.println(location + "灯光已打开");
}
public void off() {
isOn = false;
System.out.println(location + "灯光已关闭");
}
}
// 电视接收者
public static class TV {
private String location;
private boolean isOn;
public TV(String location) {
this.location = location;
}
public void on() {
isOn = true;
System.out.println(location + "电视已打开");
}
public void off() {
isOn = false;
System.out.println(location + "电视已关闭");
}
}
// 开灯命令
public static class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.on();
}
@Override
public void undo() {
light.off();
}
}
// 关灯命令(其他命令类似)
public static class LightOffCommand implements Command {
private Light light;
public LightOffCommand(Light light) {
this.light = light;
}
// 实现代码类似,execute()调用light.off(),undo()调用light.on()
@Override
public void execute() {
light.off();
}
@Override
public void undo() {
light.on();
}
}
public static class TVOnCommand implements Command {
// 持有电视接收者的引用
private TV tv;
// 通过构造函数注入接收者
public TVOnCommand(TV tv) {
this.tv = tv;
}
// 执行命令:调用电视的打开方法
@Override
public void execute() {
tv.on();
}
// 撤销命令:对应的反向操作是关闭电视
@Override
public void undo() {
tv.off();
}
}
public static class TVOffCommand implements Command {
// 持有电视接收者的引用,通过构造函数注入
private TV tv;
public TVOffCommand(TV tv) {
this.tv = tv;
}
// 执行命令:调用电视的关闭方法
@Override
public void execute() {
tv.off();
}
// 撤销命令:对应的反向操作是打开电视
@Override
public void undo() {
tv.on();
}
}
public static class RemoteControl {
private Command command;
private Command lastCommand; // 用于撤销操作
public void setCommand(Command command) {
this.command = command;
}
// 执行命令
public void pressButton() {
command.execute();
lastCommand = command; // 记录最后执行的命令
}
// 撤销命令
public void pressUndoButton() {
if (lastCommand != null) {
lastCommand.undo();
}
}
}
}
运行结果
--- 执行命令 ---
客厅灯光已打开
客厅电视已打开
--- 撤销命令 ---
客厅电视已关闭
客厅灯光已关闭
--- 执行关闭命令 ---
客厅灯光已关闭
命令模式的核心价值
解耦发送者和接收者:调用者无需知道接收者是谁以及如何执行操作
支持命令队列和批处理:可以将多个命令组合成宏命令一次性执行
支持撤销和重做:通过记录命令历史实现操作回滚
支持日志记录:可以记录命令执行日志,用于审计或故障恢复
命令模式在 GUI 操作、事务管理、任务调度等场景中应用广泛,例如:
文本编辑器的撤销 / 重做功能
数据库事务的提交 / 回滚
任务调度框架中的任务封装
遥控器、菜单等交互组件的命令封装