设计模式学习笔记 命令模式

发布 2021-03-07 00:11:28 阅读 5356

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

提供了用统一方法执行不同行为的简单机制。

允许在运行时改变所处理的请求,以及如何处理请求。

仅仅需要很少的**实现。

当条件调度程序已经足够的时候,会增加设计的复杂度。

命令模式将发出请求的对象和执行请求的对象解耦。

在被解耦的两者之间是通过命令对象进行沟通的。命令对象封装了接收者和一个或一组动作。

调用者通过调用命令对象的execute()发出请求,这会使得接收者的动作被调用。

调用者可以接受命令当做参数,甚至在运行时动态地进行。

命令可以支持撤销,做法是实现一个undo()方法来回到execute()被执行前的状态。

宏命令是命令的一种简单的延伸,允许调用多个命令。宏方法也可以支持撤销。

实际操作时,很常见使用“聪明”命令对象,也就是直接实现了请求,而不是将工作委托给接受者。

命令也可以用来实现日志和事务系统。

许多系统都会收到、发送并处理请求。条件调度程序是一条条件语句,它用来执行请求的发送和处理。有些条件调度程序很适合它们要完成的任务。有些则并不适合。

适合任务的条件调度程序往往只是把少量的请求发送到少量的处理逻辑中。这种调度程序的**往往可以在一屏内显示,我们不需要滚动屏幕。通常情况下,用command模式替换这种条件调度程序并没有什么益处。

另一方面,即使条件调度程序很小,它也可能不适合你的系统。把条件调度程序重构为基于command的解决方案,有两个最常见的理由。

1) 缺少足够的运行时灵活性。依赖于条件调度程序的客户**需要用新的请求或处理逻辑动态的配置这个条件调度程序。然而,这个条件调度程序并不支持这种动态的配置,因为所有的发送和处理逻辑都被硬编码在单一的条件语句中。

2) **体的膨胀。有些条件调度程序会变得巨大而笨拙,因为它们会逐渐增加对新请求的处理或者处理逻辑会因职责的增加而变得更复杂。把处理逻辑提取到不同的方法中并不会有很大的帮助,因为包含条件调度程序和提取出的方法的类仍然太庞大。

command模式为这种问题提供了极好的解决方案。为了实现它,只需要简单把每块请求处理逻辑放到一个单独的“命令”类中,这个类有一个通用的方法,如execute()或run(),用来执行它所封装的处理逻辑。一旦有了这样一批命令类,就可以用一个集合来存储、获取它们的实例;添加、删除或修改实例;并通过调用它们的执行方法执行这些实例。

用一种统一的方法发送请求并执行不同的行为,对设计来说是如此的重要,以至于你可能会发现自己已经直接使用了command模式,而不是过后进行重构。我开发过得许多服务端的、基于web的系统都使用了command模式为发送请求、执行动作或**动作提供一种标准方法。

设计模式》的作者解释了如何用command模式来支持撤销操作/恢复操作。在极限编程周期中经常会产生的一个问题是,当你不清楚一个系统是否需要撤销/恢复操作功能时,应该怎么办。是完全实现command模式以防万一?

还是完成完全实现command模式,即使这样做违反了“你根本不需要它”,这个xp原则告诫我们不要为**添加基于臆测的、实际上不需要的功能。如果不清楚一个系统是否需要command模式,我一般不会实现它,因为在需要时实现这个模式并不困难。然而,如果**变得越来越难以重构实现command模式,并且之后需要撤销/恢复操作功能的机会很大,那么在变得困难之前重构实现就很有意思了。

这很像上保险。

command模式很容易实现,很通用,也非常有用。

见《重构与模式》7.6章节。

1、在包含条件调度程序的类中找到处理请求的**,在这段**上应用提炼方法重构,直到产生执行该**行为的执行方法为止。

2、重复步骤1,把所有剩余的请求处理**提炼到各自的执行方法中。

3、在每个执行方法上应用提炼类重构,产生处理请求的具体命令。通常的做法是把具体命令中的执行方法声明为公共。如果在新的具体命令中的执行方法过于庞大或难于理解,应用组合方法重构。

创建了所有具体命令之后,寻找它们中的重复**。如果存在重复**,考虑是否可以通过应用形成template method重构去除它。

4、定义一个命令,及声明了与每个具体命令相同的执行方法的接口或抽象类。为实现这一步,需要分析具体命令,找到它们独特或相似的地方。找到下面问题的答案。

必须为通用执行方法传入什么参数?

在具体命令的构造过程中,可以传入什么参数?

通过**参数,而不是直接传入数据,具体命令可以获得什么信息?

这个执行方法的最简签名是什么?

考虑在具体命令上应用提炼超类重构或提炼接口重构,产生命令的早期版本。

5、使每个具体命令都实现或继承这个命令,并用命令类型更新所有具体命令的客户**。

6、在包含条件调度程序的类中,定义并组装一个命令映射,这个映射包含每个具体命令,并用唯一标识符作为主键,在运行时可以用这个主键获取命令。

如果具体命令很多,那么为命令映射添加具体命令的**也会很多。在这种情况下,考虑把具体命令实现为plugin模式,这个模式来自patterns of enterprise application architecture。这样就可以通过提供适当的配置数据来简单地装载它们(例如,命令类的名字列表,类所在的目录更好)。

7、在包含条件调度程序的类中,把调度请求的条件**替换为获取正确的具体命令并调用其执行方法的**。这个类现在就是一个invoker了。

public class catalogapp else if(all_

xmlbuilder allworkshopsxml = new xmlbuilder("workshops");

workshoprepository respository =

iterator ids =

while(

string id = string)

workshop workshop =

workshop");

id", name",

status",

duration",

string formattedxml = getformatteddata(

return new handlerresponse(new stringbuffer(formattedxml), all_workshop_stylesheet);

many more 'else if' statements

public class catalogapp else if(all_

private void getnewworkshopresponse(map parameters) {

string nextworkshopid =

stringbuffer newworkshopcontents =

设计模式学习笔记

创建型模式。抽象工厂生成器工厂方法原型单件适配器桥接组合装饰外观享元 职责链。abstract factorybuilderfactory 可产生一系列类的对象复杂步骤逐步创建对象。拷贝对象原型。全局一个实例,一个访问点对象结构型模式。将一个类的接口进行转换后兼容,解决接口不匹配。将抽象部分与实现部...

设计模式入门学习工厂模式

先读一本设计模式入门书,深入浅出设计模式,之后再拜读一下gof设计模式。工作也有两年时间了,说设计模式接触的应该比较多了,只是一直没有进行系统的整理。说起来,刚入职做webkit这让我有一个比较高的技术起点,技术视界也比较宽广。抓时间系统过一遍设计模式,下编码的艺术。工厂模式 为创建对象提供过渡接口...

C设计模式学习

1 设计模式之开篇。很长时间没有写文章了,前段时间写的c 语法糖分享得到有很多朋友支持,这个也使得我有信心继续分享下去,在这里非常感谢大家!这次开始给大家分享一下设计模式,我个人觉得设计模式也对于我们提高个人技术水平来说也是一个必不可少的知识点,最近我有重新温习了一下设计模式,今天把我学习时的心得给...