设计模式之命令模式

150 阅读3分钟

命令模式

命令模式能够帮助我们将请求发起者和请求执行者分离开来,实现解耦的目的。 以下将从几个方面展开论述:

  • 命令模式的业务场景。

  • 命令模式的uml表示。

  • 知名框架中的运用。

  • 应用场景和优缺点

命令模式的业务场景

举一个餐厅的例子,你去餐厅点菜,喊来服务员跟她讲要哪个菜,服务员记下来了以后,找厨师做菜。 image.png 发现了没有,服务员和厨师耦合在一起了。如果这个时候厨师在忙呢,没有厨师跟这个服务员对接,服务员也就等在这里了。

image.png

实线箭头表示依赖关系。现在我希望让Waiter和Chef之间解耦,也就是让Waiter和Chef之间的实线箭头消失。

接下来我们换成命令模式的餐厅。

你去餐厅点菜,喊来服务员跟她讲要哪个菜,服务员用订单记录了下来。服务员自带一个“能够让厨师做菜”的命令,收到订单后,只要执行这个出餐命令就好了。

image.png

这是UML图。

image.png

发现了没有,原来是Waiter和Chef直接相连的,现在Waiter和Chef没有直接相连,实现解耦了。

命令模式的uml表示

命令模式的uml表示如下图所示。 image.png

接下来做一一解释。 Invoker和command之间是聚合关系,表示一个invoker可以持有多个command。 Command和ConcreateCommand之间是extends关系,斜体Command表示抽象类,空心三角形表示extends。 ConcreateCommand和Receiver之间是关联关系,表示ConcreateCommand持有Receiver。 Client虽然是持有关系,但是可以看作成依赖关系。

以下是基于UML图生成的代码。

image.png

知名框架中的运用

JDK中的Runnable接口就是典型的命令模式使用。 Invoker: 也就是Thread,thread里面关联了一个private Runnable runnable; Command: 也就是Runable接口。 Receiver: 取决于你自己的业务逻辑。

有Receiver的情况。

image.png

无Receiver的情况。

image.png

分析JDK这么做的好处。

  1. 如果没有Runnable接口,那么Thread要访问某一个对象,就势必会和被访问对象耦合起来。
  2. 有了Runnable接口之后,Thread和被访问对象,也就是Receiver对象解耦了。

应用场景和优缺点

命令模式的应用场景:

  1. 系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。
  2. 系统需要在不同的时间指定请求、将请求排队和执行请求。
  3. 系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作。

命令模式的优点:

  1. 降低系统的耦合度。命令模式能将调用操作的对象与实现该操作的对象解耦。
  2. 增加或删除命令非常方便。采用命令模式增加与删除命令不会影响其他类,它满足“开闭原则”,对扩展比较灵活。 3. 可以实现宏命令。 命令模式可以与组合模式结合,将多个命令装配成一个组合命令,即宏命令。
  3. 方便实现 Undo 和 Redo。命令模式可以与后面介绍的备忘录模式结合,实现命令的撤销与恢复。

命令模式的缺点:

  1. 使用命令模式可能会导致某些系统有过多的具体命令类。
  2. 系统结构更加复杂。