概述
调用1个动作,我们一般做法就是直接调用,比如开灯的话就是:light.On(),这样做很好,但如何实现针对这个动作来实现undo,redo呢,我们就会感觉有点犯傻了,因为light.On()是一个方法,Undo(),Redo()也是方法,一个方法怎么调用方法呢,其实,换一个思路,把一个方法转为一个中间类,不就解决了。
ps:我们设计的时候如果2个类耦合严重,那么我们可以考虑一个中间层,把a与b的依赖关系转化为让a依赖于c,b依赖于c
命令模式呢就是把一个方法封装为一个命令类,uml视图如下
需求分析
还是来看实例,我们现在做一个家庭的遥控器,有2组按钮,1组为开灯,关灯,1组为开电视,关电视。直接调用的话,代码可以写成这样:
这段代码很好,干净利落,我们其实都会这样写。但如果需求改变了呢,比如我们要加第3组按钮,比如我们要换第1组按钮为开门,关门呢,ok,我们会发现需要不断修改,那我们在最后添加一组按钮,Undo,Redo呢,按照这个框架,傻眼了吧。那么我们就可以用到command的模式了,把每个动作封装为一个类,比如Light有2个动作on,off,就设计为2个类,Light.On封装为LightOnCommand,Light.Off封装为LightOffCommand,
,uml图如下
具体实现
首先是Light和TV2个实际的Receiver类,如下:
然后是设计ICommand接口:如下
4个command类,LightOnCommand 对应的是Light.On,LightOffCommand 对应Light.Off,TVOnCommand对应TV.On,TVOffCommand对应TV.Off,如下
注意:这里每个Command在类内部实现了Undo,Redo,所以当调用Command的时候,就都具有了Undo,Redo功能。
方法都封装为Command类了,然后就是调用者了,这里就是RemoteControler,负责绑定Command,最终用户通过RemoteControler调用Command.代码如下
最后就是客户实现测试代码了:
结果:(2个on指令,1个undo指令,1个redo指令)
the light is on
the TV is on
the TV is off
the TV is on
下一篇: 《Head First Design Patterns》笔记七:适配器模式(Adapter Pattern)
上一篇: 《Head First Design Patterns》笔记五:单件模式(Singleton Pattern)