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

命令模式把方法调用封装起来,通过封装方法调用,我们可以把运算块包装成形。所以调用此运算的对象不需要关心事情是如何进行的,只要知道如何使用包装成形的方法来完成它就可以。

问题描述

上面的问题描述,看上去一头雾水,我们只要记住命令模式的3个角色:调用者:按钮;接收者:具体的装置;命令:绑定给调用者的行为。

1. 让我们看看遥控器

整体的业务流程是:按钮按下后,命令就调用action()函数,然后action()函数就会调用接收者的行为。

2. 仔细看看装置的类

思考一下:如果按照正常的写法,我们是不是会直接在调用者中,实例化接收者,然后依次调用接收者的行为类。

这种方法的缺陷,1. 简单而言,耦合性太高;2. 然后呢,如果装置改变了,那么调用者的代码就会跟着改变。

3. 命令模式

简单而言,我们发现上面的缺陷是可以解决的,可以用命令模式将“动作的请求者”从“动作的执行者”对象中解耦。

可以这样理解:调用者不直接调用执行者,而是绑定一个命令对象,用命令对象的方法去调用执行者、这个命令对象有实际的动作执行者,和action函数,所以成功解耦。

这样来说,当我们装置需要改变时,我们可以直接重新给调用者绑定一个命令对象即可。

下面展示通用的命令模式的类图:

我们可以看到上面的调用者,命令类以及接收者三者的关系。

如果不是很清晰,没有关系,我们实现以下遥控器的代码就会更加清晰。

3.1 实现命令接口

3.2 实现一个打开电灯的命令(命令类中包含了接收者)

3.3 调用者(使用命令对象)

3.4 我们简单的测试

如果,装置换了,那么我们重新setCommand()方法即可。

定义命令模式:我们知道一个命令对象通过在特定接收者上绑定一组动作来封装一个请求。这个对象只暴露出一个execute()方法供调用者调用。

4. 我们基于命令模式实现遥控器

实现遥控器(调用者)

实现命令

让我们开始测试遥控器

注意:

基于命令模式的类,我们给出遥控器的类图

5. 实现undo()

我们需要在遥控器上面加上撤销的功能,将上一个动作撤销掉,很简单,往下看。

还有一个问题,我们要让遥控器追踪到上一次按下的是什么命令?然后基于该命令执行undo()

每个遥控器都需要有party模式,就是说一次调用很多个命令来运行

定义一个新命令,传入一个命令的数组,然后依次执行即可。

6. 命令模式的应用

队列请求

日志请求

总结: