Head First 设计模式 —— 06. 命令 (Command) 模式

命令模式

将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。 P206
命令模式

特点
  • 使请求调用者和请求接收者解耦 P207
  • 适合用来建立有弹性的设计,维持开闭原则 (同装饰器模式 P104
  • 使用宏命令可以一次执行其他一系列命令 P225
缺点
  • 存大量具体的命令类

思考题

命令模式的设计如何支持请求调用者和请求接收者之间的解耦? P207

  • 通过将请求接受者封装进一个命令对象,并将请求接收者的一系列动作封装成一个命令对象的方法,使得请求调用者只用持有命令对象,而不用关心其内部的请求接受者。请求调用者不知道哪个请求接受者执行了哪些动作。 P206

空对象

当不想返回一个有意义的对象是,可以使用空对象;也可以将处理 null 的责任转义给空对象。 P214

  • Java8 中的 java.util.Optional<T> 就通过使用空对象的方式,让用户可以进行链式调用,而不用主动处理 null

思考题

我们的宏命令唯一缺少的是撤销功能。一个宏命令被执行完,然后按下撤销按钮,那么宏内所进行的每一道命令都必须被撤销。请在下面代码中,填入 undo() 方法的内容: P214

public class MacroCommand implements Command {
    Command[] commands;
    
    public MacroCommand(Command[] commands) {
        this.commands = commands;
    }
    
    public void execute() {
        for(int i = 0; i < commands.length; ++i) {
            commands[i].execute();
        }
    }
    
    public void undo() {
        // 想到动作可能和当前状态有关,所以逆序撤销
        for(int i = commands.length - 1; i >= 0; --i) {
            commands[i].undo();
        }
    }
}

思考题

你认为 Web 服务器如何应用这样的队列方式?还能想到任何其他的应用吗? P228

  • 所有请求都先放入一个工作队列中,然后请求处理器不断从工作队列中取请求进行处理。
    任务的异步调用使用了工作队列。

所思所想

  • 刚看完书感觉命令模式和策略模式没有太大区别,后来阅读其他资料并仔细思考了一下,认为他们的侧重点不一样。策略模式侧重于执行某一个动作的不同实现逻辑,而命令模式侧重于执行不同的动作。(应该可以这样理解:策略模式只知道做什么动作,不知道动作如何完成;命令模式既不知道做什么动作,也不知道动作如何完成。)
  • 学了命令模式才发现,好多常用的写法/工具(线程池、工作队列、事件监听器等)都是运用了命令模式。觉得观察者模式中的 Observer 用到了命令模式,Observer 就是CommandObserver 列表就是 Command 列表。

本文首发于公众号:满赋诸机(点击查看原文) 开源在 GitHub :reading-notes/head-first-design-patterns

posted @ 2021-01-09 11:27  满赋诸机  阅读(161)  评论(0编辑  收藏  举报