设计模式系列-命令模式

最后更新于:2022-04-01 20:25:33

### 一、开篇 上一篇我们讲述了结构型模式中的代理模式。本篇,我们将会开始讲述行为型模式中的命令模式,在设计模式的这些基本的模式完成后,我将会将一些经常用的其他的一些扩展的模式进行讲解,希望能够引起大家的共鸣。 我们先来看看命令模式的定义吧: 命令模式是将一类对象的功能操作进行抽象,一般来说,这些对象有相同的方法,所以这类对象有着类似的操作,我们通过抽象,就可以定义出一个命令对象,通过这样的方式,用户程序在使用的时候,只与该命令对象打交道,而不用与一类对象打交道,降低了耦合性,提高了程序设计的灵活性。 命令模式适应于一组对象他们的操作形式非常的类似,这个时候我们可以把对象的行为进行抽象,抽象成命令对象,实现解耦,下面来举例说明: 例如我这里要实现多数据的保存操作,例如支持SQLServer与Oracle数据库,还有Access数据库,那么假设我这里定义相关的CRUD方法如下: [![image](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-16_573996b6afc25.png "image")](http://images.cnblogs.com/cnblogs_com/hegezhou_hot/201102/201102261526529321.png) 对于上述的方法,可能我们为每个数据库定义了自己的相应的数据库操作命令方法,例如我们都定义为Create方法,Update方法,Delete方法, Retrieve方法(查询数据)。 那么我们可以抽象出一个公共的命令对象,定义这样的命令抽象对象: [![image](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-16_573996b6cee65.png "image")](http://images.cnblogs.com/cnblogs_com/hegezhou_hot/201102/201102261526585662.png) 本篇以此为题目展开,来讲述命令模式的完整实现,可能功能还不是很完善,但是希望大家能够看出命令模式解决的问题及解决问题的思路,如果我某个地方表述有误或者说表达的不清楚,请大家指出批评,并谢谢大家的意见和建议。 ### 二、摘要 本篇将以多数据访问支持来题目来讲述命令模式的用法,可能部分功能没有讲到或者提到,还请大家补充,由于本文都是个人对命令模式的理解,可能部分观点还存在理解上的偏差,或者不深入,还请大家批评指出。 本文将从下面的几个内容展开说明: 1、命令模式的使用场景 2、命令模式的经典实现。 3、命令模式的其他应用。 4、总结命令模式。  我们看看经典的命令模式的类图吧,对比下经典命令模式的,我们下面给出命令模式的其他应用场景。 [![cf59c6de57f78257ccbf1ab1](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-16_573996b6e4a42.jpg "cf59c6de57f78257ccbf1ab1")](http://images.cnblogs.com/cnblogs_com/hegezhou_hot/201102/201102261527054130.jpg) ### 三、本文大纲 a、开篇。 b、摘要。 c、本文大纲。 d、命令模式的特点及使用场景。 e、命令模式的其他方案。 f、命令模式使用总结。 g、系列进度。 h、下篇预告。 ### 四、命令模式的特点及使用场景 我们来分析下命令模式的使用场景吧,一般情况下如下几类场景中使用命令模式会达到很好的效果: 1、当一个应用程序调用者与多个目标对象之间存在调用关系时,并且目标对象之间的操作很类似的时候。 2、例如当一个目标对象内部的方法调用太复杂,或者内部的方法需要协作才能完成对象的某个特点操作时。 3、有时候调用者调用目标对象后,需要回调一些方法。 对于上图中的静态对象,我们来进行解释下,并且我们必须深入理解这几个对象的含义。 Invoker:调用者对象。 Receiver:接收调用者请求执行操作的目标对象。 ICommand:用于解耦目标对象与调用者之间的抽象命令对象。 下面我们来分析下上面讲述的CRUD的经典命令模式的实现: 1、定义SQLServer的CRUD的简单实现示例代码: [![image](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-16_573996b704ae3.png "image")](http://images.cnblogs.com/cnblogs_com/hegezhou_hot/201102/20110226152709113.png) [![image](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-16_573996b72a670.png "image")](http://images.cnblogs.com/cnblogs_com/hegezhou_hot/201102/201102261527218235.png) [![image](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-16_573996b742f0f.png "image")](http://images.cnblogs.com/cnblogs_com/hegezhou_hot/201102/201102261527317702.png) [![image](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-16_573996b766206.png "image")](http://images.cnblogs.com/cnblogs_com/hegezhou_hot/201102/201102261527464198.png) 这里补上DO方法: [![image](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-16_573996b78d479.png "image")](http://images.cnblogs.com/cnblogs_com/hegezhou_hot/201102/201102270842345198.png) 2、CRUD的ICommand接口定义: [![image](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-16_573996b7aa087.png "image")](http://images.cnblogs.com/cnblogs_com/hegezhou_hot/201102/201102261527525490.png) [![image](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-16_573996b7bfb29.png "image")](http://images.cnblogs.com/cnblogs_com/hegezhou_hot/201102/201102261527585103.png) 我们这里定义的Receiver定义成枚举类型的对象,来枚举SQLserver执行的具体的操作。 3、下面给出命令对象的基本实现: [![image](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-16_573996b7dcad2.png "image")](http://images.cnblogs.com/cnblogs_com/hegezhou_hot/201102/201102261528065706.png) 4、具体的命令对象的实现: [![image](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-16_573996b80136a.png "image")](http://images.cnblogs.com/cnblogs_com/hegezhou_hot/201102/201102261528143702.png) 5、调用者代码 [![image](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-16_573996b816df1.png "image")](http://images.cnblogs.com/cnblogs_com/hegezhou_hot/201102/201102261528369090.png) 6、测试代码: [![image](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-16_573996b835358.png "image")](http://images.cnblogs.com/cnblogs_com/hegezhou_hot/201102/201102261528541701.png) 通过上面我们给出了命令模式的一个经典的实现方案。下面我们来看看其他的解决方案。在实际的项目中,可能我们很少会设置上面的Receiver对象的,也很少把他作为command的一个属性放在接口中。我们更习惯将Receiver对象作为ICommand中通用接口方法的一个变量传入给目标对象。当然不同的场景决定了不同的模式用法。通过经典的方案,我们能够看出命令模式的用法。 ### 五、命令模式的其他实现方案 一、轻量级的事件队列 考虑如下场景,如果我们可能在某个调用者在执行一个动作时,我们不想调用者了解那么多的细节和内部的交互,并且调用者的这个方法调用了很多目标对象的不同方法,来协作完成一些操作。这些目标对象的方法要么顺序有限制,要么无顺序的限制等。 1、创建3个类,每个类都有自身的成员方法输出一段字符串 [![image](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-16_573996b84ca8f.png "image")](http://images.cnblogs.com/cnblogs_com/hegezhou_hot/201102/201102261529027221.png) 2、定义一个委托 [![image](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-16_573996b862365.png "image")](http://images.cnblogs.com/cnblogs_com/hegezhou_hot/201102/201102261529261921.png) 3、定义调用者 [![image](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-16_573996f473c68.png "image")](http://images.cnblogs.com/cnblogs_com/hegezhou_hot/201102/201102261529387602.png) 4、测试代码 [![image](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-16_573996f4978a7.png "image")](http://images.cnblogs.com/cnblogs_com/hegezhou_hot/201102/201102261532385659.png) 5、输出结果: [![image](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-16_573996f4b009d.png "image")](http://images.cnblogs.com/cnblogs_com/hegezhou_hot/201102/201102261532527794.png) 二、异步命令 考虑现实我们在开发的过程中经常会遇到这样的场景吧:我们需要执行一个时间特别长的任务,如果我们将这个长任务与其他的任务一起采用同步执行的方式,客户的体验不好,例如我们在下载的时候,如果我们能做到异步的方式的话,后台执行文件下载的操作,前台用户可以继续执行其他的操作,而不是等待下载完毕,才能继续操作。这个时候,我们可能通过异步命令的方式来操作,效果肯定会更好。不然也不会出现那么多的异步编程的思想了。 下面我们通过命令模式来实现异步命令模式: 1、  定义命令抽象接口 [![image](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-16_573996f4c9676.png "image")](http://images.cnblogs.com/cnblogs_com/hegezhou_hot/201102/201102261533007492.png) 2、定义异步命令接口 [![image](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-16_573996f4ddeb4.png "image")](http://images.cnblogs.com/cnblogs_com/hegezhou_hot/201102/201102261533152037.png) 3、异步命令抽象的实现 [![image](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-16_573996f50699d.png "image")](http://images.cnblogs.com/cnblogs_com/hegezhou_hot/201102/201102261533215313.png) [![image](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-16_573996f525911.png "image")](http://images.cnblogs.com/cnblogs_com/hegezhou_hot/201102/201102261533283441.png) 上面给出了异步的调用方式,通过上面的这样的代码形式,就能完成异步的访问 4、实体的内容 [![image](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-16_573996f536a06.png "image")](http://images.cnblogs.com/cnblogs_com/hegezhou_hot/201102/201102261533343370.png) 上面实体的内容可以改进成为,通过统一添加的方式来注册事件 具体的调用方式如下: [![image](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-16_573996f550527.png "image")](http://images.cnblogs.com/cnblogs_com/hegezhou_hot/201102/201102270842371488.png) ### 六、命令模式使用总结 通过上面的讲解我想大家应该对命令模式有了一定的了解,命令模式就是将一组对象的相似行为,进行了抽象,将调用者与被调用者之间进行解耦,提高了应用的灵活性。命令模式将调用的目标对象的一些异构性给封装起来,通过统一的方式来为调用者提供服务。 相信大家通过实战能够体会该模式的好处。 ### 七、系列进度 创建型 1、[设计模式系列-单件模式](http://www.cnblogs.com/hegezhou_hot/archive/2010/10/02/1841390.html) 2、[设计模式系列-工厂模式](http://www.cnblogs.com/hegezhou_hot/archive/2010/11/30/1892227.html#1973367) 3、设计模式系列[-抽象工厂模式](http://www.cnblogs.com/hegezhou_hot/archive/2010/12/01/1893388.html) 4、设计模式系列[-创建者模式](http://www.cnblogs.com/hegezhou_hot/archive/2010/12/02/1894771.html) 5、设计模式系列[-原型模式](http://www.cnblogs.com/hegezhou_hot/archive/2010/12/04/1896471.html) 结构型 1、[设计模式系列-组合模式](http://www.cnblogs.com/hegezhou_hot/archive/2010/12/06/1898161.html#commentform) 2、[设计模式系列-外观模式](http://www.cnblogs.com/hegezhou_hot/archive/2010/12/06/1897398.html) 3、[设计模式系列-适配器模式](http://www.cnblogs.com/hegezhou_hot/archive/2010/12/09/1901040.html) 4、[设计模式系列-桥模式](http://www.cnblogs.com/hegezhou_hot/archive/2010/12/10/1902185.html) 5、[设计模式系列-装饰模式](http://www.cnblogs.com/hegezhou_hot/archive/2010/12/11/1903392.html) 6、[设计模式系列-享元模式](http://www.cnblogs.com/hegezhou_hot/archive/2010/12/12/1903728.html) 7、[设计模式系列-代理模式](http://www.cnblogs.com/hegezhou_hot/archive/2011/02/20/1958965.html) 行为型 1、设计模式系列-命令模式 2、设计模式系列-观察者模式 3、设计模式系列-策略模式 4、设计模式系列-职责模式 5、设计模式系列-模板模式 6、设计模式系列-中介者模式 7、设计模式系列-解释器模式 ### 八、下篇预告 下一篇我将会讲解设计模式中的经典模式,观察者模式,该模式是委托应用的经典代表,不熟悉委托的话,可能就会很好理解该模式。希望大家提出宝贵意见,我将会不断的改进写作的水平,希望与大家共同交流和进步。
';