python 实现 命令模式

本文的目录地址

本文的代码地址

现在多数应用都有撤销操作。虽然难以想象,但是在很多年里,任何软件中确实都不存在撤销操作。撤销操作是在1974年引入的,但Fortran和Lisp分别早在1957年和1958年就已创建了撤销操作,这两门语言仍在被人广泛使用。在那些年里,我真心不想使用应用软件。犯了一个错误,用户也没什么便捷方式修正它。

历史就讲到这里。我们想知道如何在应用中实现撤销功能。那就是命令模式(Command pattern)

命令设计模式帮助我们将一个操作(撤销、重做、复制、粘贴等)封装成一个对象。简而言之,这意味着创建一个类,包含实现该操作所需要的所有逻辑和方法。这样做的优势如下所述。

  • 我们并不需要直接执行一个命令。命令可以按照希望执行。
  • 调用命令的对象与指导如何执行命令的对象解耦。调用者无需知道命令的任何实现细节。
  • 如果有意义,可以把多个命令组织起来,这样调用者能够按顺序执行它们。例如,在实现一个多层撤销命令时,这是很有用的。

软件的例子

PyQt是QT工具包的Python绑定。PyQt包含一个QAction类,将一个动作建模为一个命令。对每个动作都支持额外的可选信息,比如,描述、工具提示、快捷键和其他。

git-cola是使用Python语言编写的一个Git GUI,它使用命令模式来修改模型、变更一次提交、应用一个差异选择、签出等。

应用案例
许多开发人员以为撤销例子是命令模式的唯一应用案例。撤销操作确实是命令模式的杀手级特性,然而命令模式能做的实际上还有很多。
 GUI按钮和菜单项:前面提过的PyQt例子使用命令模式来实现按钮和菜单项上的动作。
 其他操作:除了撤销,命令模式可用于实现任何操作。其中一些例子包括剪切、复制、粘贴、重做和文本大写。
 事务型行为和日志记录:事务型行为和日志记录对于为变更记录一份持久化日志是很重要的。操作系统用它来从系统崩溃中恢复,关系型数据库用它来实现事务,文件系统用它来实现快照,而安装程序(向导程序)用它来恢复取消的安装。
 宏:在这里,宏是指一个动作序列,可在任意时间点按要求进行录制和执行。流行的编辑器(比如,Emacs和Vim)都支持宏。

实现

我们将使用命令模式实现最基本的文件操作工具。
 创建一个文件,并随意写入一个字符串
 读取一个文件的内容
 重命名一个文件
 删除一个文件
我们并不从头实现这些工具程序,因为Python在os模块中已提供了良好的实现。我们想做的是在已有实现之上添加一个额外的抽象层,这样可以当作命令来使用。这样,我们就能获得命令提供的所有优势。
下面的用例图展示了实现将支持的用户可执行操作。从展示的操作可以看出,重命名文件和创建文件支持撤销。删除一个文件和读取文件内容不支持撤销。对于文件删除操作实际上是可以实现撤销的,一种技术是使用一个特殊的垃圾箱/废物篓目录来存储所有被删除文件,这样在用户请求时可以恢复出来。这是所有现代桌面环境使用的默认行为,就留作练习吧。


verbose是个全局变量,为true代表会输出一些附加信息。CreateFile命令包含三个部分,初始化部分(这个init方法中我给它添加了默认内容,为了读取文件内容的方便)、执行部分和undo部分;ReadFile命令包含init和execute两个部分;RenameFile命令包含三个部分,init,execute,undo。命令不一定非要是类才行,这里delete_file是一个方法。完整的代码请点击command.py,下面是运行效果:

[Create file "file1"]
[Reading file "file1"]
file content
[renaming file1 to file2]
reverse the excuted commands? [y/n]y
[renaming file2 back to file1]
[undo creating file "file1"]

Process finished with exit code 0

文件删除是用一个函数来实现的,我们可以把它放入到commands列表,像其余命令那样去执行吗?我们知道在Python中函数是一等公民,因此我们可以执行某些操作。为此我们更改了main函数内容并写入到代码文件first-class.py,下面是运行结果:

[deleting file "file1"]

Process finished with exit code 0


猜你喜欢

转载自blog.csdn.net/hbu_pig/article/details/80807322