大数据知识体系
首页
数据结构与算法
  • JVM
  • Java
  • Scala
  • Python
设计模式
  • MySQL
  • Redis
  • HDFS
  • HBase
  • ClickHouse
  • ElasticSearch
  • Iceberg
  • Hudi
  • Spark
  • Flink
  • Hive
  • Yarn
  • Zookeeper
  • Maven
  • Git
  • 数据仓库
  • 用户画像
  • 指标体系
数据治理
关于
首页
数据结构与算法
  • JVM
  • Java
  • Scala
  • Python
设计模式
  • MySQL
  • Redis
  • HDFS
  • HBase
  • ClickHouse
  • ElasticSearch
  • Iceberg
  • Hudi
  • Spark
  • Flink
  • Hive
  • Yarn
  • Zookeeper
  • Maven
  • Git
  • 数据仓库
  • 用户画像
  • 指标体系
数据治理
关于
  • 设计模式概述
  • 创建型模式

    • 单例模式
    • 简单工厂模式
    • 工厂方法模式
    • 抽象工厂模式
    • 建造者模式
    • 原型模式
  • 结构型模式

    • 适配器模式
    • 装饰器模式
    • 代理模式
    • 外观模式
    • 桥接模式
    • 组合模式
    • 享元模式
  • 行为型模式

    • 策略模式
    • 模板方法模式
    • 观察者模式
    • 迭代器模式
    • 责任链模式
    • 命令模式
      • 一、概述
        • 1.1 解决了什么问题
        • 1.2 解决方案
      • 二、实现方式
        • 2.1 角色
        • 2.2 代码
      • 三、源码中的应用
    • 备忘录模式
    • 状态模式
    • 访问者模式
    • 中介者模式
    • 解释器模式
  • 设计模式
  • 行为型模式
Will
2022-03-29
目录

命令模式

# 一、概述

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

在命令模式中,会将一个请求封装为一个对象,以便使用不同的参数来表示不同的请求,且该请求支持撤销操作。

# 1.1 解决了什么问题

命令模式最大的特点是解耦。

小李到公司楼下的兰州牛肉面(是兰州牛肉面,不是兰州拉面)吃饭,整个就餐的过程是这样的:

  1. 小李告诉服务员自己要吃什么(可能是二细、大宽、也可能是炒拉条)
  2. 服务员告诉后厨,来一碗二细、或者大宽、扩折炒拉条
  3. 后厨用自己的方式维护了一个出餐列表
  4. 后厨根据不同的订单进行制作,并将制作好的菜品放到窗口由小李自己获取

这整个流程等其实就是命令模式,它很通过服务员完美解耦了小李和后厨,小李只需要发送命令,他不需要关心命令的具体执行者是谁,而且在命令被具体执行之前都可以撤销。

# 1.2 解决方案

通过在客户端和命令执行者之间增加调用者做到解耦。

虽然命令模式实现了解耦,但同时会增加代码量,因为每个命令都需要创建一个类。

# 二、实现方式

# 2.1 角色

  1. Invoker:命令调用者,负责对请求进行初始化,其中必须包含一个成员变量来存储对命令对象的引用。调用者不会直接创建命令对象,而是通过构造函数从客户端获得预先生成的命令。
  2. Receiver:命令执行者,负责完成实际的工作。
  3. Command:抽象的命令接口,通常只要䘝执行命令的方法。
  4. Concrete Command:具体的命令,实现 Command 接口,每个命令都对应一个具体的命令类。
  5. Client:创建一个具体的命令。

# 2.2 代码

Command 接口:

public interface Command {
    void execute();
}
1
2
3

Concrete Command:

public class ErxiCommand implements Command {

    private BeefNoodlesWorker worker;

    public ErxiCommand(BeefNoodlesWorker worker) {
        this.worker = worker;
    }

    @Override
    public void execute() {
        this.worker.makeErxi();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
public class DakuanCommand implements Command {

    private BeefNoodlesWorker worker;

    public DakuanCommand(BeefNoodlesWorker worker) {
        this.worker = worker;
    }

    @Override
    public void execute() {
        this.worker.makeDakuan();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
public class ChaolatiaoCommand implements Command {

    private ChaomianWorker worker;

    public ChaolatiaoCommand(ChaomianWorker worker) {
        this.worker = worker;
    }

    @Override
    public void execute() {
        this.worker.makeChaolatiao();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

Receiver:

/**
 * 牛肉面厨师
 */
public class BeefNoodlesWorker {
    public void makeErxi() {
        System.out.println("二细制作完成");
    }

    public void makeDakuan() {
        System.out.println("大宽制作完成");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
public class ChaomianWorker {
    public void makeChaolatiao() {
        System.out.println("炒拉条制作完成");
    }

    public void makeChaomian() {
        System.out.println("炒面制作完成");
    }
}
1
2
3
4
5
6
7
8
9

命令调用者:

public class Invoker {

    private final List<Command> commands = new ArrayList<>();

    public void addCommand(Command command) {
        commands.add(command);
        System.out.println("添加命令成功:" + command.getClass().getSimpleName());
    }

    public void executeCommand() {
        for (Command command : commands) {
            command.execute();
        }
    }

    public void UndoCommand(Command command) {
        if (commands.remove(command)) {
            System.out.println("撤销命令成功:" + command.getClass().getSimpleName());
        } else {
            System.out.println("撤销命令失败:" + command.getClass().getSimpleName());
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

客户端:

public class CommandTest {
    public static void main(String[] args) {
        // 对应服务员
        Invoker invoker = new Invoker();

        // 命令执行者
        BeefNoodlesWorker beefNoodlesWorker = new BeefNoodlesWorker();
        ChaomianWorker chaomianWorker = new ChaomianWorker();

        // 构建具体的命令,每个命令都会绑定具体的执行者
        ErxiCommand erxiCommand = new ErxiCommand(beefNoodlesWorker);
        DakuanCommand dakuanCommand = new DakuanCommand(beefNoodlesWorker);
        ChaolatiaoCommand chaolatiaoCommand = new ChaolatiaoCommand(chaomianWorker);

        // 构建执行计划
        invoker.addCommand(erxiCommand);
        invoker.addCommand(dakuanCommand);
        invoker.addCommand(chaolatiaoCommand);

        invoker.UndoCommand(dakuanCommand);

        invoker.executeCommand();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
添加命令成功:ErxiCommand
添加命令成功:DakuanCommand
添加命令成功:ChaolatiaoCommand
撤销命令成功:DakuanCommand
二细制作完成
炒拉条制作完成
1
2
3
4
5
6

# 三、源码中的应用

java.lang.Runnable

上次更新: 2023/11/01, 03:11:44

← 责任链模式 备忘录模式→

Theme by Vdoing | Copyright © 2022-2023 Will 蜀ICP备2022002285号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式