大话设计模式
字体: 16 + -

第189章

为什么使用命令模式大b:“上边的代码是否看起来很傻呢,本来可以这样简单实现的。”

publicclassclient{

publicstaticvoidmain(string[]args){

receiverreceiver=newreceiver();

receiver.actionone();

receiver.actiontwo();

}

}

publicclassreceiver{

publicreceiver(){

//

}

publicvoidactionone(){

system.out.println(“actiononehasbeentaken.”);

}

publicvoidactiontwo(){

system.out.println(“actiontwohasbeentaken.”);

}

}

大b:“看!多简洁。如果是像上边如此简单的需求,这个才应该是我们的选择,但是有些情况下这样的写法不能解决的,或者说解决起来不好,所以引入命令模式。1、我们须要client和receiver同时开发,而且在开发过程中分别须要不停重构,改名。2、如果我们要求redo,undo等功能。3、我们须要命令不按照调用执行,而是按照执行时的情况排序,执行。4、开发后期,我们发现必须要log哪些方法执行了,如何在尽量少更改代码的情况下实现,并且渐少重复代码。5、在上边的情况下,我们的接受者有很多,不止一个。”

小a:“当我们遇到这些情况时应该怎样去解决?”

大b:“解决办法:情况一、我们可以定义一个接口,让receiver实现这个接口,client按照接口调用。情况二、我们可以让receiver记住一些状态,例如执行前的自己的状态,用来undo,但自己记录自己的状态实现起来比较混乱,一般都是一个累记录另一个类的状态。情况三、很难实现。情况四、我们须要在每个action,前后加上log。”情况五、相对好实现,但是再加上这个,是否感觉最终的实现很混乱呢?

大b:“好,我们再来看看命令模式,在命令模式中,我们增加一些过渡的类,这些类就是上边的命名接口和命令实现,这样就很好的解决了情况一、情况二。我们再加入一个invoker,这样情况三和情况四就比较好解决了。”

如下加入log和排序后的。

publicclassinvoker{

privatelistcmdlist=newarraylist();

publicinvoker(){

}

publicadd(commandmand){

cmdlist.add(mand);

}

publicremove(commandmand){

cmdlist.remove(mand);

}

publicvoidaction(){

commandcmd;

while((cmd=getcmd())!=null){

log(“begin”+cmd.getname());

cmd.execute();

log(“end”+cmd.getname());

}

}

publiccommandgetcmd(){

//按照自定义优先级,排序取出。

}

}

publicclassclient{

publicstaticvoidmain(string[]args){

receiverreceiver=newreceiver();

commandmandone=newconcretecommandone(receiver);

commandmandtwo=newconcretecommandtwo(receiver);

invokerinvoker=newinvoker();

invoker.add(mandone);

invoker.add(mandtwo);

iinvoker.action();

}

}