设计模式之命令模式(Command)
定义:
将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作。(网上很多地方引用的定义)
将请求封装成对象,以便使用不同的请求、队列或日志来参数化其他对象。命令模式也支持可撤销的操作。 (Head First 的定义)
解读: 请求说的更傻一点就是求别人为自己服务,对应到程序中,向别人提供服务的话好像离不开方法,请求大概就是对方法的调用了。不过请求这个词语,感觉有点怪怪。因为我调用B对象的C方法,不怎么像是向B请求C倒是像强制B执行C,B有不执行C的权利吗?(当开个玩笑)。提到参数化,就会想到"定义一个参数",参数说白了就是一个占位符、一个变量到时想放什么放什么。参数化就先理解成变量化、动态化吧。“从而使你可用不同的请求对客户进行参数化”这句话还是很难理解啊,关键是这个"客户".客户肯定是服务享受者嘛,那就应该是命令的调用者,好像不太合理。Head First 中有一句话,"一整天下来,女招待参数化了许多订单。这个对应到命令模式的理解就是命令传递着参数化命令对象,即命令对象(或者命令接口更合理吧)成为命令传递者的一个(组)成员,或其函数中的参数。再直接看看Head First中的定义,根据"一整天下来,女招待参数化了许多订单" 我们知道"其他对象"就是命令对象。使用不同请求来参数化命令对象,在这里请求理解成方法调用已经不合适了。把请求在程序中说到底就是一种命令,"命令对象"--就是命令接口,翻来覆去翻来覆去成了把命令接口动态的实例化成命令对象。晕死,写了这么多我当在写小品剧本。
再说一下封装,封装一般就是隐藏具体细节,提高独立性。有时候还可以见到把某某功能封装到一个对象,这个似乎有点像外包。算了打住打住。。。
http://www.javathinker.org/main.jsp?bc=showessay.jsp&filename=java/fengzhuang.htm
结构图
一个命令大概也就涉及到5个东西,命令发送者、命令传递者、命令本身(就是命令对象嘛)、命令执行者、命令执行结果(不考虑)。
描述:
允许"发送请求的对象"和"接受并执行这些请求的对象分割开来"。算了受那个定义的打击我还是用自己的话补充一下吧,调用者和执行者之间相互解耦,命令对象中本身包含了执行者的信息。调用者只需要有一个命令对象,就可以完成他要的工作。执行者的每一种可能的操作都封装成一种命令,调用者识别的是命令的抽象。
这样调用者是独立于执行者的能力的增长、变化的。 (调用者对应类图下面的命令传递者吧)
实例分析:
下面我们来看看电风扇
这是电风扇类
//命令接口 实现操作,和撤销功能。
//命令对象具有电风扇的引用。CeilingFanHightCommand 是把电风扇调为高档的命令对象,对应还有中档 CeilingFanMediumCommand、低档、关闭对象
所有的实际操作都有电风扇自己完成。现在我们暂时不考虑撤销操作,也就是不用理会 IUndo 和 CeilingFanUndo;
测试代码:
看到这里好像没有发现调用者和执行者之间的解耦。 上面代码中有电风扇,有命令对象。测试代码应该在调用者中还是传递者中呢。
命令模式代码下载