莫度编程网

技术文章干货、编程学习教程与开发工具分享

JAVA命令模式适用场景,优缺点是什么你知道吗,这篇文章彻底讲透

一句话定义命令模式: 将请求封装为对象,实现请求调用者与执行者的解耦。 用代码说话,拒绝废话!


一、适用场景(直接上代码案例)

场景:智能家居遥控器
假设我们需要控制灯、空调、音响等设备,要求支持:

  1. 一键执行多个设备操作
  2. 支持操作撤销(Undo)
  3. 支持宏命令(批量操作)

传统写法痛点:

// 调用者直接依赖具体设备
Light light = new Light();
AirConditioner ac = new AirConditioner();

// 实现“回家模式”(开灯+开空调)
light.on();
ac.on();

// 问题1:撤销操作需记录状态,代码混乱
// 问题2:新增设备需修改调用代码,违反开闭原则

二、命令模式解决方案(附完整代码)

1. 核心角色

  • Command(命令接口)
  • ConcreteCommand(具体命令)
  • Invoker(调用者/遥控器)
  • Receiver(接收者/设备)

2. 代码实现

// 1. 命令接口
interface Command {
    void execute();
    void undo(); // 支持撤销
}

// 2. 接收者(设备实现)
class Light {
    void on() { System.out.println("开灯"); }
    void off() { System.out.println("关灯"); }
}

class AirConditioner {
    void on() { System.out.println("开空调"); }
    void off() { System.out.println("关空调"); }
}

// 3. 具体命令(封装操作)
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 ACOnCommand implements Command {
    private AirConditioner ac;
    public ACOnCommand(AirConditioner ac) { this.ac = ac; }
    @Override
    public void execute() { ac.on(); }
    @Override
    public void undo() { ac.off(); }
}

// 4. 宏命令(批量操作)
class MacroCommand implements Command {
    private List<Command> commands = new ArrayList<>();
    public void addCommand(Command cmd) { commands.add(cmd); }
    @Override
    public void execute() {
        for (Command cmd : commands) cmd.execute();
    }
    @Override
    public void undo() {
        // 逆序撤销
        for (int i = commands.size() - 1; i >= 0; i--) {
            commands.get(i).undo();
        }
    }
}

// 5. 调用者(遥控器)
class RemoteControl {
    private Command command;
    public void setCommand(Command command) { this.command = command; }
    public void pressButton() { command.execute(); }
    public void pressUndo() { command.undo(); }
}

// 6. 客户端使用
public class Client {
    public static void main(String[] args) {
        // 创建设备
        Light light = new Light();
        AirConditioner ac = new AirConditioner();

        // 创建命令
        Command lightOn = new LightOnCommand(light);
        Command acOn = new ACOnCommand(ac);

        // 创建宏命令(回家模式:开灯+开空调)
        MacroCommand homeMode = new MacroCommand();
        homeMode.addCommand(lightOn);
        homeMode.addCommand(acOn);

        // 遥控器绑定宏命令
        RemoteControl remote = new RemoteControl();
        remote.setCommand(homeMode);

        // 一键执行
        remote.pressButton(); // 输出:开灯 开空调
        remote.pressUndo();   // 输出:关空调 关灯(逆序撤销)
    }
}

三、四大核心应用场景

  1. 需要解耦调用者与执行者
  • 遥控器(Invoker)不直接操作设备,通过Command接口调用。
  1. 支持撤销/重做操作
  • 每个Command实现undo()方法(如编辑器撤销功能)。
  1. 需要支持事务操作
  • 宏命令保证批量操作原子性(全部成功或全部撤销)。
  1. 队列请求/延迟执行
  • 将Command存入队列,线程池异步执行(如订单处理系统)。

四、优缺点(表格对比)

优点

缺点

解耦调用者与执行者
(遥控器不关心设备细节)

类爆炸
(每个命令需一个具体类)

支持撤销/重做
(完美支持事务回滚)

过度设计
(简单请求不如直接调用)

易于扩展新命令
(符合开闭原则)


支持组合命令
(宏命令实现复杂操作)



五、实战经验总结

  1. 优先使用场景
  • 需要撤销/重做功能(如绘图软件)
  • 系统需要解耦调用链(如消息队列)
  1. 避免滥用场景
  • 简单请求直接调用(new Light().on()
  • 对性能要求极高的场景(多一层封装损耗)
  1. 开源框架应用
  • Java AWT的ActionEvent(命令模式变体)
  • Spring JMS的MessageListener(解耦消息处理)

关键结论:命令模式的核心价值是“将请求封装为对象”,从而获得解耦、扩展性与事务控制能力。

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言

    Powered By Z-BlogPHP 1.7.4

    蜀ICP备2024111239号-43