设计模式之-命令模式

一、定义

命令模式(Command Pattern)是一种行为型设计模式,它将一个请求封装为一个对象,从而使你可以用不同的请求、队列或者日志来参数化其他对象,也支持可撤销的操作。

换句话说,命令模式将“动作的调用者”和“动作的执行者”解耦,通过封装请求(命令对象)达到请求调用和执行分离。

二、适用场景

  • 需要将请求调用者与请求接收者解耦,使调用者不必知道请求的具体执行细节;
  • 需要支持对请求的队列、日志、撤销和重做操作;
  • 需要将一组操作封装成一个命令,实现事务式的调用;
  • 需要将操作参数化,支持动态组合和扩展。

三、核心角色

角色

说明

Command

抽象命令,声明执行命令的接口

ConcreteCommand

具体命令,实现抽象命令接口,绑定接收者和动作

Receiver

接收者,负责具体执行命令相关的业务逻辑

Invoker

调用者,负责命令的请求和调用

Client

客户端,负责创建具体命令并设置接收者和调用者

四、UML 类图

+----------------+         +-----------------------+         +--------------+
|   Client       |         |      Invoker          |         |  Receiver    |
+----------------+         +-----------------------+         +--------------+
         |                          |                             |
         | 1. 创建命令                |                            |
         |------------------------->|                              |
         |                          | 2. 保存命令                  |
         |                          |----------------------------->|
         |                          |                              |
         |                          | 3. 调用命令执行               |
         |                          |----------------------------->|
+----------------+          +-----------------------+         +--------------+
|  Command       |<-------->| ConcreteCommand       |         |              |
+----------------+          +-----------------------+         +--------------+
| +execute()     |          | +execute()            |         | +action()    |
+----------------+          +-----------------------+         +--------------+

五、真实业务场景示例:智能家居遥控器

假设你有一个智能家居系统,包含灯(Light)、空调(AirConditioner)等设备,需要实现遥控器控制设备的开关操作,且支持操作撤销。

1. 抽象命令接口(Command 角色)

/**
 * 抽象命令接口,声明执行和撤销命令方法
 */
public interface Command {
    void execute();
    void undo();
}

2. 接收者类(Receiver 角色)

/**
 * 灯,执行具体开关操作
 */
public class Light {
    private String location;

    public Light(String location) {
        this.location = location;
    }

    public void on() {
        System.out.println(location + " 灯打开");
    }

    public void off() {
        System.out.println(location + " 灯关闭");
    }
}

/**
 * 空调,执行具体开关操作
 */
public class AirConditioner {
    public void on() {
        System.out.println("空调打开");
    }

    public void off() {
        System.out.println("空调关闭");
    }
}

3. 具体命令类(ConcreteCommand 角色)

/**
 * 灯的开命令
 */
public 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 class LightOffCommand implements Command {
    private Light light;

    public LightOffCommand(Light light) {
        this.light = light;
    }

    @Override
    public void execute() {
        light.off();
    }

    @Override
    public void undo() {
        light.on();
    }
}

/**
 * 空调开命令
 */
public class AirConditionerOnCommand implements Command {
    private AirConditioner ac;

    public AirConditionerOnCommand(AirConditioner ac) {
        this.ac = ac;
    }

    @Override
    public void execute() {
        ac.on();
    }

    @Override
    public void undo() {
        ac.off();
    }
}

/**
 * 空调关命令
 */
public class AirConditionerOffCommand implements Command {
    private AirConditioner ac;

    public AirConditionerOffCommand(AirConditioner ac) {
        this.ac = ac;
    }

    @Override
    public void execute() {
        ac.off();
    }

    @Override
    public void undo() {
        ac.on();
    }
}

4. 调用者类(Invoker 角色)

/**
 * 遥控器,调用命令执行和撤销
 */
public class RemoteControl {
    private Command slot;         // 这里简单用一个槽位模拟按键
    private Command lastCommand;  // 用于撤销操作

    public void setCommand(Command command) {
        this.slot = command;
    }

    public void pressButton() {
        slot.execute();
        lastCommand = slot;
    }

    public void pressUndo() {
        if (lastCommand != null) {
            lastCommand.undo();
        }
    }
}

5. 客户端代码(Client)

public class CommandPatternDemo {
    public static void main(String[] args) {
        // 创建接收者
        Light livingRoomLight = new Light("客厅");
        AirConditioner ac = new AirConditioner();

        // 创建具体命令
        Command lightOn = new LightOnCommand(livingRoomLight);
        Command lightOff = new LightOffCommand(livingRoomLight);
        Command acOn = new AirConditionerOnCommand(ac);
        Command acOff = new AirConditionerOffCommand(ac);

        // 创建调用者
        RemoteControl remote = new RemoteControl();

        // 控制灯开
        remote.setCommand(lightOn);
        remote.pressButton();

        // 撤销灯开操作
        remote.pressUndo();

        // 控制空调开
        remote.setCommand(acOn);
        remote.pressButton();

        // 控制灯关
        remote.setCommand(lightOff);
        remote.pressButton();

        // 撤销灯关操作
        remote.pressUndo();
    }
}

六、类与角色对照表

类名

模式角色

说明

Command

抽象命令

定义命令接口

LightOnCommand

具体命令

绑定灯的开操作

LightOffCommand

具体命令

绑定灯的关操作

AirConditionerOnCommand

具体命令

绑定空调开操作

AirConditionerOffCommand

具体命令

绑定空调关操作

Light

接收者

执行灯的具体操作

AirConditioner

接收者

执行空调的具体操作

RemoteControl

调用者

调用命令,执行或撤销

CommandPatternDemo

客户端

组装命令和调用者

七、优缺点分析(Pros & Cons)

✅ 优点

优点

说明

解耦调用者和接收者

调用者只需要调用命令接口,不需要知道具体操作

易于扩展命令

新命令只需实现命令接口,无需改动调用者

支持撤销和恢复

命令可记录状态,实现撤销操作

支持宏命令

可以组合多个命令,支持批量执行

❌ 缺点

缺点

说明

命令类膨胀

命令类数量随着请求种类增长,可能变多

设计复杂度提升

增加了系统复杂度,学习和理解成本较高

八、真实业务应用场景

场景

说明

GUI 按钮操作

将按钮操作封装为命令,支持撤销重做

事务管理

将数据库操作封装为命令,实现事务回滚

远程调用

将请求封装为命令,支持异步和队列处理

宏命令

将多个命令组合成宏命令,批量执行

智能家居控制

设备操作封装成命令,遥控器调用,支持撤销

九、总结(Summary)

命令模式通过封装请求,实现调用者和执行者的解耦,使系统更加灵活和易于扩展。它不仅方便支持撤销、重做操作,也利于事务和队列处理,是行为型设计模式中非常实用的一种。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码蚁Q

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值