简介
假设你有一个智能家居遥控器,上面有多个按钮,每个按钮对应不同的设备操作(如开灯、关灯、调空调温度)。
命令模式的解决方案是:
- 将每个操作(如“开灯”)封装成一个独立的命令对象,包含执行和撤销方法。
- 遥控器(调用者)不直接控制设备,而是通过触发命令对象来间接操作设备。
- 你可以灵活地为按钮更换命令,甚至实现“一键多操作”或“撤销”功能。
适用场景
- 需要将请求发送者与接收者解耦(如菜单项触发不同操作)。
- 支持请求的排队、撤销/重做、日志记录(如文本编辑器的撤销功能)。
- 需要支持宏命令(一键执行多个命令)。
优点
- 解耦请求发送者和接收者,增强扩展性。
- 支持撤销、重做、事务等复杂操作。
缺点
- 每个命令需单独实现类,增加代码量。
- 复杂命令可能引入多层嵌套逻辑。
类图
代码
// 命令接口
interface Command {
void execute();
void undo();
}
// 接收者:灯
class Light {
public void on() {
System.out.println("灯已打开");
}
public void off() {
System.out.println("灯已关闭");
}
}
// 具体命令:开灯
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();
}
}
// 调用者:遥控器按钮
class RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
}
public void pressUndo() {
command.undo();
}
}
// 客户端
public class CommandDemo {
public static void main(String[] args) {
Light light = new Light();
Command lightOn = new LightOnCommand(light);
RemoteControl remote = new RemoteControl();
remote.setCommand(lightOn);
remote.pressButton(); // 执行命令
remote.pressUndo(); // 撤销命令
}
}
应用场景
数据库事务中的操作可通过命令模式实现,支持执行与回滚。
import java.util.Stack;
// 事务命令接口
interface TransactionCommand {
void execute();
void rollback();
}
// 接收者:数据库操作
class Database {
public void insert(String data) {
System.out.println("插入数据: " + data);
}
public void delete(String data) {
System.out.println("删除数据: " + data);
}
}
// 具体命令:插入操作
class InsertCommand implements TransactionCommand {
private Database db;
private String data;
public InsertCommand(Database db, String data) {
this.db = db;
this.data = data;
}
@Override
public void execute() {
db.insert(data);
}
@Override
public void rollback() {
db.delete(data);
}
}
// 事务管理器(支持回滚)
class TransactionManager {
private Stack<TransactionCommand> history = new Stack<>();
public void submit(TransactionCommand command) {
command.execute();
history.push(command);
}
public void rollbackAll() {
while (!history.isEmpty()) {
history.pop().rollback();
}
}
}
// 客户端
public class TransactionDemo {
public static void main(String[] args) {
Database db = new Database();
TransactionManager manager = new TransactionManager();
manager.submit(new InsertCommand(db, "A"));
manager.submit(new InsertCommand(db, "B"));
System.out.println("\n回滚事务:");
manager.rollbackAll();
}
}