命令模式:解耦请求与执行的优雅之道

发布于:2025-06-13 ⋅ 阅读:(13) ⋅ 点赞:(0)

引言:软件设计的解耦艺术

在软件开发中,我们常面临请求发起者请求执行者之间的紧密耦合问题。这种耦合会导致:

  • 系统扩展困难:新增命令需要修改现有代码
  • 功能复用受限:相同操作无法在不同上下文中重用
  • 撤销/重做复杂:操作历史难以追踪和管理

命令模式正是为解决这类问题而生的设计模式。它将请求封装成独立对象,允许你参数化客户端使用不同的请求、队列或日志请求,并支持可撤销的操作。本文将深入解析命令模式的原理、实现及高级应用场景。


一、模式定义与核心思想

1.1 官方定义

命令模式 (Command Pattern):将请求封装成对象,从而让你使用不同的请求、队列或日志请求来参数化其他对象,并支持可撤销的操作。

1.2 设计哲学

调用者Invoker
命令接口Command
具体命令ConcreteCommand
接收者Receiver

核心原则

  1. 解耦调用与执行:调用者无需知道接收者细节
  2. 命令对象化:将操作封装为可传递的对象
  3. 支持扩展:新增命令不影响现有系统结构

二、模式结构解析

2.1 UML类图

classDiagram
    class Invoker {
        -command: Command
        +setCommand(Command)
        +executeCommand()
    }
    
    interface Command {
        <<interface>>
        +execute()
        +undo()
    }
    
    class ConcreteCommand {
        -receiver: Receiver
        -state
        +execute()
        +undo()
    }
    
    class Receiver {
        +action()
    }
    
    Invoker o--> Command
    Command <|.. ConcreteCommand
    ConcreteCommand --> 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;
    }
    
    @Override
    public void execute() {
   
        light.on();
    }
    
    @Override
    public 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;
    }
    
    @Override
    public void execute() {
   
        prevTemperature = ac.getTemperature();
        ac.setTemperature(newTemperature);
    }
    
    @Override
    public void undo</