文章目录
- 1 命令模式简介
- 2 命令模式的特点和目的
- 2.1 命令模式通常使用以下术语:
- 2.1.1 命令模式的UML类图
- 2.2 命令模式的主要目的如下
- 2.3 命令模式可用于以下各种情景:
- 3 命令模式python代码示例
- 4 命令模式的优点和缺点
- 4.1 优点
- 4.2 缺点
1 命令模式简介
正如我们在上一章中所看到的那样,行为模式侧重于对象的响应性。它利用对象之间的交互实现更强大的功能。命令模式也是一种行为设计模式,其中对象用于封装在完成一项操作时或在触发一个事件时所需的全部信息。这些信息包括以下内容:
- 方法名称;
- 拥有方法的对象;
- 方法参数的值。
我们用一个非常简单的软件例子来理解该模式,如安装向导。通常情况下,安装向导通过多个步骤或屏幕来了解用户的偏好。因此,当用户使用向导时,他/她需要做出某些选择。通常来说,向导可以使用命令模式来实现。向导首先会启动一个名为 command 的对象。用户在向导的多个步骤中指定的首选项或选项将存储在 command 对象中。当用户在向导的最后一个屏幕上单击 Finish 按钮时,Command 对象就会运行execute()方法该方法会考察所有存储的选项并完成相应的安装过程。因此,关于选择的所有信息被封装在稍后用于采取动作的对象中。
2 命令模式的特点和目的
2.1 命令模式通常使用以下术语:
- Command、Receiver、Invoker 和 client:Command 对象了解 Receiver 对象的情况,并能调用 Receiver 对象的方法
- 调用者方法的参数值存储在command 对象中;
- 调用者知道如何执行命令;
- 客户端用来创建command 对象并设置其接收者。
2.1.1 命令模式的UML类图
整个流程图是非常简单的,客户端请求执行命令,调用者接受命令,封装它并将其放置到队列中。ConcreteCommand类根据所请求的命令来指导接收者执行特定的动作。
2.2 命令模式的主要目的如下
- 将请求封装为对象。
- 可用不同的请求对客户进行参数化。
- 允许将请求保存在队列中(我们将在本章后面进行讨论)。
- 提供面向对象的回调。
2.3 命令模式可用于以下各种情景:
- 根据需要执行的操作对对象进行参数化。
- 将操作添加到队列并在不同地点执行请求;。
- 创建一个结构来根据较小操作完成高级操作
3 命令模式python代码示例
场景:假设我们想要开发一个安装向导,或者更常见的安装程序。通常,安装意味着需要根据用户做出的选择来复制或移动文件系统中的文件。在下面的示例中,我们首先在客户端代码中创建Wizard 对象,然后使用preferences()方法存储用户在向导的各个屏幕期间做出的选择。在向导中单击 Finish 按钮时,就会调用 execute()方法。之后,execute()方法将会根据首选项来开始安装。
class Wizard():
def __init__(self, src, rootdir):
self.choices = []
self.rootdir = rootdir
self.src = src
def preferences(self, command):
self.choices .append(command)
def execute(self):
for choice in self.choices:
if list(choice.values())[0]:
print("Copying binaries --", self.src," to ",self.rootdir)
else:
print("No Operation")
if __name__ == '__main__':
## Client code
wizard = Wizard('python3.5.gzip','/usr/bin/')
## Users chooses to installPythononly
wizard.preferences({'python':True})
wizard.preferences({'java':False})
wizard.execute()
4 命令模式的优点和缺点
4.1 优点
- 将调用操作的类与知道如何执行该操作的对象解耦。
- 提供队列系统后,可以创建一系列命令。
- 添加新命令更加容易,并且无需更改现有代码。
- 还可以使用命令模式来定义回滚系统,例如,在向导示例中,我们可以编写一个回滚方法。
4.2 缺点
- 为了实现目标,需要大量的类和对象进行协作。应用程序开发人员为了正确开发这些类,需要倍加小心;
- 每个单独的命令都是一个 concreteCommand 类,从而增加了需要实现和维护的类的数量。