【转】 命令模式

原文链接:http://baijiahao.baidu.com/s?id=1587032070903401093&wfr=spider&for=pc


命令模式(Command Pattern)

将一个请求封装为一个对象,可让请求变得灵活(请求对象参数化),同时将请求者和请求接收者解耦。比如,A对象想调用B对象的某个方法,那么A对象必然需要依赖B对象;使用命令模式的话就类似抽取出一个公共地方(请求对象),A依赖请求对象,A只需调用请求对象的方法,然后由请求对象调用B对象的方法,这样A和B就成功的解耦了;请求者无需关心接收者是谁,只需要维护好请求对象即可,需要变更接收者时只需跟换请求对象即可,这样使得系统易扩展,也符合开放闭合原则。命令模式整体的一个基本结构如下图所示:

命令模式结构

模式案例解析

这里我们以事物的提交和回滚为例来解说命令模式;为一个insert方法增加事物,如果没有出现异常则事物提交,否则事物回滚,针对的是事物的提交和回滚操作,我们把事物当做是一个请求对象(command),把具体实现数据库事物提交和回滚的对象作为接收者(receiver),把insert这个方法的对象作为请求发起者(invoke);具体类结构图如下所示:

命令模式

Command(抽象命令对象):它是命令对象的抽象(父类),可以是接口、抽象类或者普通类(案例中使用接口),它定义了一组命令对象的统一业务接口方法;这里定义了execut()(命令执行方法:案例中表示事务提交),undo()(命令撤销方法:案例中表示事务回滚)。具体代码片段如下所示:

抽象命令对象

扫描二维码关注公众号,回复: 1018923 查看本文章

TransactionalCommand(具体命令对象):它实现了抽象命令对象的方法,同时拥有一个命令接收者(TransactionalReceiver)的引用,在execut和undo方法中分别调用命令接收者的方法。具体代码片段如下所示:

具体命令对象

TransactionalReceiver(接收者对象):实现具体命令对应的业务方法。具体代码片段如下所示:

接收者对象

DataDao(业务数据操作对象:请求调用者):它是具体请求的调用者,拥有了一个命令对象(Command)的引用,在insert方法中实现了对应命令方法的调用(提交事务、回滚事务)。具体代码片段如下所示:

请求调用者

Client(客户端测试):具体代码片段如下所示:

客户端测试

扩展

命令队列:当一个请求对应多个接收者时,可以使用命令对象形式来实现。就是增加一个命令队列的对象,请求调用者不在依赖请求对象,而是依赖于命令对象队列,命令对象队列中维护了一个保护抽象请求对象(命令对象)的集合,在命令对象队列中通过循环抽象命令集合进行接收者调用。

撤销操作:在命令模式中,我们可以通过调用一个命令对象的execute()方法来实现对请求的处理,如果需要撤销(Undo)请求,可通过在命令类中增加一个逆向操作来实现。

总结

优点

降低系统的耦合度(请求者和接收者解耦)

容易进行新命令的增加(易扩展),而不需要修改原代码,符合开发闭合原则

缺点

系统中可能需要提供大量的具体命令类,这将影响命令模式的使用

适用场景

有时候需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是什么。此时希望用一种松耦合的方式来设计程序,使得请求发送者和请求接收者能够消除彼此之间的耦合关系。

猜你喜欢

转载自blog.csdn.net/AJ1101/article/details/80373487