今天的博客中就来系统的整理一下“命令模式”。说到命令模式,我就想起了控制台(Console)中的命令。无论是Windows操作系统(cmd.exe)还是Linux操作系统(命令行式shell(Command Line Interface shell ,即CLI shell)都有命令行程序。说白了就是你输入你要执行的命令提示符,然后计算机就还是根据你所下达的命令来执行。你最终看到的是命令执行后的结果,具体的执行细节不需要你一步步的去下达命令。(与之前博客保持一致,我们仍然使用Swift语言来进行实现)

进一步说,你下达的命令是一个总的命令,而计算机执行时是讲该命令分为不同的阶段来执行的。举个简单的例子,当你打开计算机是,你只需按一下开机键,也就是下达你的Start命令。此时计算机收都命令后就会执行硬盘启动、点亮屏幕、加载系统等等一系列的操作,而这些操作都是你下达Start命令后其自动完成的。再比如,你使用Linux系统下的Shell时,你会在Shell中输入各种命令,然后计算机就会根据你的命令来执行系列的操作,具体哪些操作是对外隐藏的。这也就是对具体的实现细节进行了封装,并对外留出调用接口。

看完上面的描述,是时候回到今天的主题“命令模式”上了。命令模式简单的说就是将一些列的命令(函数或者方法)进行封装,隐藏内部执行细节,并对外留出调用的接口。命令模式是支持撤销操作的,撤销所做的事情就是与你刚才下达的命令相反。下方就是命令模式的定义了,说白了命令模式就是进一步对命令进行封装,简化命令的执行。这些命令在编程中就是一个个的函数。也可以说“命令模式”是对函数调用的封装,简化了函数调用的方式,隐藏了函数调用的细节。

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

今天博客中会通过命令模式来实现控制台是示例,也就是我们可以通过给控制台下达不同的命令来进行不同的操作。

一、控制台命令模式的类图

下方就是我们将要实现的控制台“命令模式”的示例的类图。下方的类图还是比较简单的,红框上方是具体的类(计算机和电灯)。这些具体的类中有属于自己的不同的命令(对应着不同的函数函数),比如Computer类(计算机)中有Start、ScreenLight、Load、StartOver、Off等命令,而Light(电灯)类中有On、Off命令。

而红框中是我们示例的核心,也就是对命令的上述具体命令的封装。在封装命令时我们会实现一个接口(该示例中是Command协议),该接口就是外部执行命令( execute() 函数)的接口。封装的不同的命令都会遵循Command协议,所以我们封装的命令都会对外暴漏一个execute()函数,用来执行我们封装的命令。在封装命令时,我们会根据封装的命令的特点来执行特定的命令。比如下方的ComputerStartCommand命令中的就会包括Start、ScreenLight、Load、StartOver等子命令。也就是说在ComputerStartCommand命令中调用了Computer中的部分命令(函数),也就是对Computer类中的函数的调用做了进一步的封装,所以ComputerStartCommand命令要依赖于Computer类的。

红框下方就是我们的Console(控制台)类,Console是依赖于命令的接口而不依赖于命令的具体实现,这对模块间的解耦是非常有用的。在Console类中的command属性就是我们所依赖的命令接口,我们可以给command赋值不同的具体命令的实现,然后在Action函数中去执行具体的命令。请参加下方的类图。

二、根据上述类图进行代码实现

上一部分对类图进了详细的介绍,接下来我们对上述类图进行代码实现就不是什么难事了。我们实现的步骤是与上面分析的步骤是一致的,自上而下。首先我们会给出Computer与Light的实现,然后是红框中的命令集合的实现,最后是Console的实现。如下所示:

1、具体命令执行对象的实现

首先我们要对真正去执行命令的对象进行代码实现,在该实例中就是Computer类和Light类。当然从上述示例中,我们不难看出这两个类要包括哪些命令(方法)。下方就是我们Computer类和Light类的具体实现,因为代码较为简单,在此就不做过多的赘述了。具体代码实现如下所示:

2.对上述设备的命令进行封装

下方代码段就是上面类图中的红框部分的代码的具体实现。我们将Command声明为协议(命令对外的接口),而LightOnCommand、LightOffCommand、ComputerStartCommand具体的命令集合都遵循与这个协议。也就是说着三种不同的命令实现对外都有统一的接口,LightOnCommand与LightOffCommand都依赖于Light类,并且根据自己的命令种类来调用Light不同的方法,这也符合面向对象设计的单一职责。ComputerStartCommand命令类则依赖于Compute外设,会调用Computer中与启动相关的具体子命令。具体代码如下所示:

3. 控制台的具体实现

上面我们实现了类图上面的两个模块,紧接着我们要实现类图最下方的那个类,也就是Console类。Console类也是比较简单的,Console类依赖于Command接口,其中的command存储属性就是用来存储那些遵循Command协议的类的对象的。在Console类中的action()方法是用来执行命令的。具体实现如下。

三、测试用例

经过上面的类图的介绍与具体的代码实现,相比对“命令模式”有点概念了吧。最后一部分我们要对上述代码的实现进行测试,看一下我们的代码实现是否有问题。下方代码截图就是我们的测试用例以及该测试用例执行后输出的结果。首先我们创建了一个控制台的对象(类似于我们打开了一个Shell窗口),然后输出不同的命令(setCommand()),最后进行执行(调用action())。测试用例具体如下所示:

至此我们的“命令模式”的一个完整示例就执行完了,最后用一句话来总结一下命令模式,那就是“命令模式是对一些列函数的调用的封装,然后留出执行的接口”。

同样今天的Demo也会在github上进行分享,分享地址为:https://github.com/lizelu/DesignPatterns-Swift

设计模式(六):控制台中的“命令模式”(Command Pattern)的更多相关文章

  1. 乐在其中设计模式(C#) - 命令模式(Command Pattern)

    原文:乐在其中设计模式(C#) - 命令模式(Command Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 命令模式(Command Pattern) 作者:webabcd ...

  2. 设计模式 - 命令模式(command pattern) 多命令 具体解释

    命令模式(command pattern) 多命令 具体解释 本文地址: http://blog.csdn.net/caroline_wendy 參考命令模式: http://blog.csdn.ne ...

  3. 设计模式 - 命令模式(command pattern) 具体解释

    命令模式(command pattern) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy 命令模式(command pattern) : 将请求封装成对 ...

  4. 设计模式 - 命令模式(command pattern) 宏命令(macro command) 具体解释

    命令模式(command pattern) 宏命令(macro command) 具体解释 本文地址: http://blog.csdn.net/caroline_wendy 參考: 命名模式(撤销) ...

  5. 设计模式 - 命令模式(command pattern) 撤销(undo) 具体解释

    命令模式(command pattern) 撤销(undo) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy 參考命令模式: http://blog.cs ...

  6. 二十四种设计模式:命令模式(Command Pattern)

    命令模式(Command Pattern) 介绍将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或记录请求日志,以及支持可取消的操作. 示例有一个Message实体类,某个 ...

  7. 设计模式-15命令模式(Command Pattern)

    1.模式动机 在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,我们只需在程序运行时指定具体的请求接收者即可,此时,可以使用命令模式来进行设计,使 ...

  8. 设计模式----行为型模式之命令模式(Command Pattern)

    下面来自head first设计模式的命令模式一章节. 定义 将"请求"封装成对象,以便使用不同的请求.队列或者日志来参数化其他对象.命令模式也支持可撤销的操作. 类图 注: 1. ...

  9. C#设计模式——命令模式(Command Pattern)

    一.概述通常来说,“行为请求者”与“行为实现者”是紧耦合的.但在某些场合,比如要对行为进行“记录.撤销/重做.事务”等处理,这种无法抵御变化的紧耦合是不合适的.在这些情况下,将“行为请求者”与“行为实 ...

随机推荐

  1. 试试SQLSERVER2014的内存优化表

    试试SQLSERVER2014的内存优化表 SQL Server 2014中的内存引擎(代号为Hekaton)将OLTP提升到了新的高度. 现在,存储引擎已整合进当前的数据库管理系统,而使用先进内存技 ...

  2. C语言 · Anagrams问题

    问题描述 Anagrams指的是具有如下特性的两个单词:在这两个单词当中,每一个英文字母(不区分大小写)所出现的次数都是相同的.例如,"Unclear"和"Nuclear ...

  3. HTML5 sessionStorage会话存储

    sessionStorage 是HTML5新增的一个会话存储对象,用于临时保存同一窗口(或标签页)的数据,在关闭窗口或标签页之后将会删除这些数据.本篇主要介绍 sessionStorage(会话存储) ...

  4. Unity 序列化

    Script Serialization http://docs.unity3d.com/Manual/script-Serialization.html 自定义序列化及例子: http://docs ...

  5. System.FormatException: GUID 应包含带 4 个短划线的 32 位数(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)。

    在NHibernate数据库查询中出现了这个错误,由于是数据库是mysql的,当定义的字段为char(36)的时候就会出现这个错误. [解决方法] 将char(36) 改成varchar(40)就行了 ...

  6. JQuery easyUI DataGrid 创建复杂列表头(译)

    » Create column groups in DataGrid The easyui DataGrid has ability to group columns, as the followin ...

  7. [EasyUI美化换肤]更换EasyUi图标

    前言 本篇文章主要是记录一些换EasyUI皮肤的过程,备忘.也欢迎美工大神各路UI给点好意见,EasyUI我就不介绍了,自行百度吧..(So..所以别问我是不是响应式..本身EasyUI就不是响应式. ...

  8. 关于SMARTFORMS文本编辑器出错

    最近在做ISH的一个打印功能,SMARTFORM的需求本身很简单,但做起来则一波三折. 使用环境是这样的:Windows 7 64bit + SAP GUI 740 Patch 5 + MS Offi ...

  9. Oracle补全日志(Supplemental logging)

    Oracle补全日志(Supplemental logging)特性因其作用的不同可分为以下几种:最小(Minimal),支持所有字段(all),支持主键(primary key),支持唯一键(uni ...

  10. ORACLE分区表梳理系列(二)- 分区表日常维护及注意事项(红字需要留意)

    版权声明:本文发布于http://www.cnblogs.com/yumiko/,版权由Yumiko_sunny所有,欢迎转载.转载时,请在文章明显位置注明原文链接.若在未经作者同意的情况下,将本文内 ...