23种设计模式之【命令模式】-核心原理与 Java 实践

文章目录

  • [命令模式(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 操作、事务管理、任务调度等场景中应用广泛,例如:

文本编辑器的撤销 / 重做功能

数据库事务的提交 / 回滚

任务调度框架中的任务封装

遥控器、菜单等交互组件的命令封装

相关推荐
vker5 小时前
第 4 天:建造者模式(Builder Pattern)—— 创建型模式
java·后端·设计模式
new_daimond6 小时前
设计模式详解:单例模式、工厂方法模式、抽象工厂模式
单例模式·设计模式·工厂方法模式
bkspiderx7 小时前
C++设计模式之创建型模式:原型模式(Prototype)
c++·设计模式·原型模式
phdsky13 小时前
【设计模式】中介者模式
c++·设计模式·中介者模式
phdsky16 小时前
【设计模式】状态模式
设计模式·状态模式
bkspiderx16 小时前
C++设计模式之创建型模式:抽象工厂模式(Abstract Factory)
c++·设计模式·抽象工厂模式
Chan1616 小时前
【 设计模式 | 创建型模式 建造者模式 】
java·spring boot·设计模式·java-ee·intellij-idea·建造者模式
澄澈i17 小时前
设计模式学习[19]---单例模式(饿汉式/懒汉式)
学习·单例模式·设计模式
bkspiderx17 小时前
C++设计模式之创建型模式:工厂方法模式(Factory Method)
c++·设计模式·工厂方法模式