今天的博客中就来系统的整理一下“命令模式”。说到命令模式,我就想起了控制台(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. 【原】AFNetworking源码阅读(三)

    [原]AFNetworking源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇的话,主要是讲了如何通过构建一个request来生成一个data tas ...

  2. 转:serialVersionUID作用

    汗,以前学了还忘了... Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的.在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本 ...

  3. 9、 Struts2验证(声明式验证、自定义验证器)

    1. 什么是Struts2 验证器 一个健壮的 web 应用程序必须确保用户输入是合法.有效的. Struts2 的输入验证 基于 XWork Validation Framework 的声明式验证: ...

  4. 第一个移动前端开源项目-dailog

    你还在为手机上没有忙碌光标而发愁吗?你还在抱怨弹出框组件要依赖zepto/jqery吗?你还在纠结是否要自己写一套还是去网上寻找成现成的UI组件吗?YouA为你轻松解决所有烦恼.YouA是我为移动前端 ...

  5. git克隆项目到本地&&全局安装依赖项目&&安装依赖包&&启动服务

     一.安装本地开发环境 1.安装本项目 在需要保存到本地的项目的文件夹,进入到文件夹里点击右键,bash here,出现下图: 2.安装依赖项目  3.安装依赖包(进入到命令行) # 安装依赖包 $ ...

  6. C++随笔:.NET CoreCLR之GC探索(3)

    有几天没写GC相关的文章了哈,今天我讲GC的方式是通过一个小的Sample来讲解,这个小的示例代码只有全部Build成功了才会有.地址为D:\coreclr2\coreclr\bin\obj\Wind ...

  7. 如何优化coding

    如何优化coding 前言 最近一直在做修改bug工作,修改bug花费时间最多的不是如何解决问题而是怎样快速读懂代码.如果代码写的好的,不用debug就可以一眼看出来哪里出了问题.实际上,我都要deb ...

  8. Java多态性——分派

    一.基本概念 Java是一门面向对象的程序设计语言,因为Java具备面向对象的三个基本特征:封装.继承和多态.这三个特征并不是各自独立的,从一定角度上看,封装和继承几乎都是为多态而准备的.多态性主要体 ...

  9. [LintCode]——目录

    Yet Another Source Code for LintCode Current Status : 232AC / 289ALL in Language C++, Up to date (20 ...

  10. VC中的MFC到底是什么?

    1. 微软基础类库(英语:Microsoft Foundation Classes,简称MFC)是一个微软公司提供的类库(class libraries),以C++类的形式封装了Windows API ...