毅四捕Go设计模式笔记——命令模式

命令模式(Command Pattern)

为了解决什么问题?

命令模式的目的是将请求发起者和请求执行者解耦,使得请求的发起者不需要知道具体的执行者是谁,也不需要知道执行的具体过程,只需要发送请求即可。

通过使用命令对象来封装请求,可以参数化和传递可调用的动作。同时,支持可撤销操作和队列请求等功能。

怎么用代码实现?

下面让我们通过一个餐厅下单的例子来看看怎么实现命令模式。例子里包含三个角色:

  • 顾客
  • 服务员
  • 厨师
    服务员在收到顾客的点餐请求后,然后将请求封装成命令,并交给厨师准备食物。

首先,定义好作为命令执行者的厨师,这里的厨师会制作汉堡包和沙拉。

java 复制代码
/**
 * 厨师接收点菜的命令并开始烹饪
 */
public class Chef {
    public void makeBurger() {
        System.out.println("Chef is making a burger");
    }
    
    public void makeSalad() {
        System.out.println("Chef is making a salad");
    }
}

然后,定义抽象下单命令,以及具体的汉堡包和沙拉的下单命令。

java 复制代码
public interface OrderCommand {
    void execute();
}

/**
 * 烹饪汉堡包的命令
 */
public class BurgerOrderCommand implements OrderCommand {
    @Override
    public void execute(Chef chef) {
        chef.makeBurger();
    }
}

/**
 * 准备沙拉的命令
 */
public class SaladOrderCommand implements OrderCommand {
    @Override
    public void execute(Chef chef) {
        chef.makeSalad();
    }
}

接着,定义服务员角色。

java 复制代码
/**
 * 服务员是命令的调用者
 */
public class Waiter {
    private Chef chef;
    private OrderCommand orderCommand;
    
    public Waiter(Chef chef) {
        this.chef = chef;
    }
    
    public void sendOrderCommandToKitchen(OrderCommand orderCommand) {
        this.orderCommand = orderCommand;
        System.out.println("Waiter sending order to kitchen...");
        orderCommand.execute(chef);
    }
}

最后,顾客通过服务员下单,让厨师做出想吃的菜品。

java 复制代码
/**
 * 餐厅顾客类
 */
public class RestaurantClient {
    public static void main(String[] args) {
        Chef chef = new Chef(); // 接收方
        Waiter waiter = new Waiter(chef); // 调用方

        OrderCommand burgerOrder = new BurgerOrderCommand(); // 顾客想吃汉堡
        waiter.sendOrderCommandToKitchen(burgerOrder); // 服务员收到顾客订单后,将订单发送至厨房

        OrderCommand saladOrder = new SaladOrderCommand(); // 顾客改主意,想吃沙拉
        waiter.sendOrderCommandToKitchen(saladOrder); // 服务员收到顾客订单后,将订单发送至厨房
    }
}

为什么可以解决这个问题?

命令模式通过将具体的请求封装成对象,使得发起请求的操作和接收请求的对象之间不直接发生依赖关系,从而实现请求发起者和请求执行者的解耦。

因为命令对象把请求封装成了对象,这使得你可以用不同的请求、队列或者日志来参数化其他对象,也可以支持撤销操作。

命令模式适用于哪些场景?

参数化对象:需要将请求参数化并传递给调用者时,可以使用命令模式。

操作排队:需要将请求排队执行,例如任务队列、线程池等。

支持撤销操作:需要提供撤销和恢复请求功能的场景。

支持宏命令:可以使用命令模式组合多个命令,实现宏命令的功能。

命令模式在开源代码中比较场景,下面是典型的案例:

Swing中的Action:Java Swing库中,javax.swing.Action接口代表了一个抽象的用户界面动作,它本身就是命令模式的一种实现。

Guava的事件总线:Guava库中的事件总线(EventBus)可以结合命令模式使用,发布者发布命令事件,而订阅者则执行相关的命令。

命令模式把发送命令的责任和执行命令的责任分开,确保了系统设计的灵活性和扩展性。此外,它还简化了其他对象的逻辑,因为它们不需要知道实际的执行逻辑。这一模式特别适用于实现撤销(redo)/恢复(undo)操作、事务系统等需要定义、存储、传递和执行请求的场合。

---------------------------------这是分割线---------------------------------

欢迎添加博主vx深入交流:

相关推荐
非优秀程序员3 分钟前
第04章 邮箱大战,163 与 QQ 的暗战|《互联网产品恩仇录》
java·vue.js·架构
知已难寻39 分钟前
Docker 入门:容器技术与 Docker 基础
java·运维·服务器·docker·云原生·容器
文丑颜不良啊3 小时前
LeetCode2481~2500题目解析
java·leetcode
Flynn Liang4 小时前
同一需求三套写法:用 Spring AI、LangChain4j、AgentScope Java 各实现一个带工具调用的 RAG 助手(实战对比)
java·人工智能·大模型·架构设计·spring ai·langchain4j·agentscope
聪明的笨猪猪4 小时前
实际工程问题:AI 生成 Spring Cache(@Cacheable / @CachePut / @CacheEvict)缓存注解踩坑
java·经验分享·面试·ai编程
愿有所息5 小时前
记一次 ARM64 + JDK8 上 fastjson2 的诡异数据错乱
java
秋饼5 小时前
MCP 2026-07-28 无状态协议大改版:Spring AI 2.1 多轮往返请求与网关路由落地
java·ai·技术分享·后端开发
SL_staff6 小时前
JVS-BI 实战:业务人员如何用零代码 ELT + 可视化配置构建实时经营分析闭环
java·spring·全栈
SL_staff7 小时前
企业AI落地难?JVS-AI渐进式实践:安全可控、小切口验证、标准化沉淀与规模化复制
java·开源·aigc
David猪大卫7 小时前
【C++修炼】map 和 set 的使用
c语言·开发语言·数据结构·c++·经验分享·笔记·学习