当前位置: 首页 > news >正文

23种设计模式-命令(Command)设计模式

命令设计模式

  • 🚩什么是命令设计模式?
  • 🚩命令设计模式的特点
  • 🚩命令设计模式的结构
  • 🚩命令设计模式的优缺点
  • 🚩命令设计模式的Java实现
  • 🚩代码总结
  • 🚩总结

🚩什么是命令设计模式?

命令设计模式(Command Pattern) 是一种 行为型设计模式,它将一个请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。

使用场景

  • 将请求调用者和请求接收者解耦

  • 支持命令的撤销(Undo)和恢复(Redo)操作

  • 支持事务系统 或 将一组操作组合成一个复合命令

  • 支持宏命令(命令队列)将命令存入日志

🚩命令设计模式的特点

  • 解耦调用者和接收者:调用者无需知道接收者的具体实现

  • 可扩展性强:可以方便地添加新的命令

  • 支持撤销和重做:可以记录命令历史实现撤销/重做功能

  • 支持事务:可以将一组命令组合成一个事务

  • 灵活性高:命令可以被排队、记录日志或延迟执行

🚩命令设计模式的结构

命令模式主要包含以下部分:

  • Command(命令接口):声明执行操作的接口

  • ConcreteCommand(具体命令):将一个接收者对象绑定于一个动作,实现执行方法

  • Invoker(调用者):要求命令对象执行请求

  • Receiver(接收者):知道如何实施与执行一个请求相关的操作

  • Client(客户端):创建具体命令对象并设置其接收者

图例:

在这里插入图片描述

🚩命令设计模式的优缺点

✅ 优点

  • 降低系统耦合度:调用者和接收者之间没有直接引用

  • 扩展性好:新增命令不会影响现有代码

  • 支持撤销/重做:可以方便地实现命令的撤销和恢复

  • 支持事务:可以将一组命令组合成一个复合命令

  • 灵活性高:可以方便地实现命令队列和日志请求

❌ 缺点

  • 可能产生过多具体命令类:每个操作都需要一个具体命令类

  • 增加系统复杂度:引入了额外的抽象层

  • 性能开销:命令对象的创建和执行可能带来额外的开销

🚩命令设计模式的Java实现

代码地址:GitHub

  • 创建 Receiver(接收者)
/**
 * @author hanson.huang
 * @version V1.0
 * @ClassName Tv
 * @Description 接收者 - 电视机
 * @date 2025/3/25 16:42
 **/
public class Tv {
    public void onAction() {
        System.out.println("电视机开机了...");
    }

    public void offAction() {
        System.out.println("电视机关机了...");
    }
}
  • 创建 Command(命令接口)
/**
 * @author hanson.huang
 * @version V1.0
 * @InterfaceName Command
 * @Description 命令接口
 * @date 2025/3/25 16:39
 **/
public interface Command {// 命令接口

    public void Execute();// 执行命令
}
  • 创建具体命令类

    • 开机命令
    /**
     * @author hanson.huang
     * @version V1.0
     * @ClassName OnCommand
     * @Description 开机命令
     * @date 2025/3/25 16:42
     **/
    public class OnCommand implements Command {
    
        private Tv tv;
    
        public OnCommand(Tv tv) {
            this.tv = tv;
        }
    
        @Override
        public void Execute() {
            tv.onAction();
        }
    }
    
    • 关机命令
    /**
     * @author hanson.huang
     * @version V1.0
     * @ClassName OffCommand
     * @Description 关机命令
     * @date 2025/3/25 16:43
     **/
    public class OffCommand implements Command {
    
        private Tv tv;
    
        public OffCommand(Tv tv) {
            this.tv = tv;
        }
    
        @Override
        public void Execute() {
            tv.offAction();
        }
    }
    
  • 创建 Invoker(调用者)

/**
 * @author hanson.huang
 * @version V1.0
 * @ClassName Invoker
 * @Description 请求者
 * @date 2025/3/25 16:40
 **/
public class Invoker { // 请求者

    private Command command;// 命令

    public void setCommand(Command command) { // 设置请求者 的 请求的命令
        this.command = command;
    }

    public void call() { // 调用
        command.Execute();
    }
}
  • 测试命令模式
/**
 * @author hanson.huang
 * @version V1.0
 * @ClassName CommandPattern
 * @Description 测试命令模式
 * @date 2025/3/25 16:44
 **/
public class CommandPattern {
    public static void main(String[] args) {
        Tv tv = new Tv(); // 接收者对象 - 电视机

        Command onCommand = new OnCommand(tv); // 开机命令
        Command offCommand = new OffCommand(tv); // 关机命令

        Invoker invoker = new Invoker(); // 调用者

        invoker.setCommand(onCommand); // 设置开机命令
        invoker.call(); // 执行命令

        System.out.println("=======================");

        invoker.setCommand(offCommand); // 设置关机命令
        invoker.call(); // 执行命令
    }
}

📌 运行结果

在这里插入图片描述

🚩代码总结

  • Tv 作为接收者知道如何执行具体的操作

  • Command 接口定义了执行命令的统一方法

  • OnCommandOffCommand 是具体命令类,绑定接收者和动作

  • Invoker 调用命令对象执行请求

  • CommandPattern 客户端创建命令对象并设置其接收者

🚩总结

  • 命令设计模式 将请求封装为对象,使不同的请求、队列或日志成为可能

  • 核心是 解耦请求发送者和接收者,使发送者无需知道接收者的具体实现

  • 适用于 需要支持撤销/重做、事务、命令队列 等场景

✅ Java源码中的应用场景:

  1. Swing/AWT中的事件处理:

    • java.awt.Actionjavax.swing.Action

    • 按钮点击等事件处理

  2. Java线程池:

    • java.lang.Runnable 接口类似于命令接口

    • 线程池执行命令对象

  3. Servlet过滤器链:

    • javax.servlet.Filter 接口定义命令模式
  4. Spring框架:

    • org.springframework.core.command.Command 接口

    • Spring Batch中的任务执行

  5. JUnit测试框架:

    • 测试用例的执行采用命令模式
  6. 数据库事务:

    • 一组SQL命令组成事务执行

创作不易,不妨点赞、收藏、关注支持一下,各位的支持就是我创作的最大动力❤️

在这里插入图片描述

相关文章:

  • 数据文件误删除,OceanBase中如何重建受影响的节点
  • Axure设计之中继器表格——拖动行排序教程(中继器)
  • 重庆软航NTKO WebOffice控件在谷歌Chrome 133版提示扩展已停用解决方案!
  • 26考研——图_图的应用(6)
  • 如何使用DeepSeek编写测试用例?
  • SCI一区 | Matlab实现DBO-TCN-LSTM-Attention多变量时间序列预测
  • 搭建Redis哨兵集群
  • 安装DNS(BIND)并部署主域服务
  • 为什么要将项目部署到外部tomcat
  • 【第13届蓝桥杯C/C++B组省赛】顺子日期
  • Brainstorm绘制功能连接图(matlab)
  • Leetcode—242. 有效的字母异位词(字符串算法)
  • 国内 npm 镜像源推荐
  • TCP/IP 协议族详细知识点清单
  • 计算机网络--传输层(1)
  • 如何在MyBatis-Plus中优雅实现复杂查询:结合`JSON_CONTAINS`与动态条件构建
  • RAG优化:python从零实现query转换增强技术
  • 从零构建大语言模型全栈开发指南:第二部分:模型架构设计与实现-2.1.3前馈网络(FFN)与激活函数(GELU)优化
  • 什么是docker-compose,和Dockerfile的区别
  • 【高项】信息系统项目管理师(十)项目风险管理【5分】
  • 拜登办公室发言人:拜登5月16日前从未被诊断出前列腺癌
  • 欧盟拟对发往欧洲的小额包裹加收手续费,外交部回应
  • 巴基斯坦一校车发生爆炸,已造成5名儿童死亡38人受伤
  • 上海地铁:9号线因雨天打滑,佘山往九亭方向部分列车限速运行
  • 竞彩湃|水晶宫夺冠后乘胜追击,四大皆空曼城人间清醒?
  • 西安市长安区与航天基地区政合一管理,党政一把手分任基地党工委正副书记