一点号前端交流2小时前
最近在看Hystrix,有博客提到这个里面使用到了命令模式。虽然命令模式在web开发中很少见,但神奇的是我也在前段时间的一次设计中使用了命令模式(或者说类似的模式)。
命令模式算是一个比较特别的模式,为什么说它特别?因为很多教你如何做好oop设计的书都会提到类似的观点:
不要把操作变成类。
然而命令模式就是把某一个操作封装成为类。
简单的说命令模式干了这样一件事:
一开始你的程序是A,B,C…对象对X,Y,Z…对象的直接操作。然后为了让(A,B,C)和(X,Y,Z)解耦,你在A和B之间加入了一个中介对象F1,F2,F3,这个中介对象的意义是包装对X,Y,Z的操作。这样你的(A,B,C)就不直接操作(X,Y,Z)了,而是使用(F1,F2,F3)对象,而这个F对象就被称为命令。
这样的好处是,这些操作可以重用。而且A,B,C与X,Y,Z是解耦的,A,B,C并不知道自己在操作什么对象,实际上他们也不知道自己在使用什么命令,它们仅仅是在调用Command的execute而已。
特别注意打包对象F1,F2,F3,和(X,Y,Z)并不是解耦的,命令对象会很清楚的知道自己在跟谁打交道。
需要理解命令模式的是,命令模式并不仅仅是解耦操作对象与被操作对象之间的关系,更重要的是,它提供了一种对象命令建模的方式。这一点也就是设计模式中所提到的命令模式所能支持的宏或者取消(undo)和重做(redo)。hystrix中对一个容错操作建模,也是为了对这个动作的一系列打包(类似提供一系列钩子),比如在这个操作之前做什么,在这个操作之后做什么,这个操作成功了要做什么,这个操作失败了要做什么,等等。
在《设计模式》提到的例子是,图形界面的菜单下拉,每一个MenuItem在被点击(调用client)的时候,才会知道哪个command被运行。
java实现public interfaceICommand{ publicvoidExecute; } public classCopyCommandimplementsICommand{ publicvoidExecute{ xxxx xxxx } } public classPasteCommandimplementsICommand{ publicvoidExecute{ xxxx xxxx } } public Class MenuItem{ private ICommand command; publicvoidClicked{ this.command.Execute; } }python实现
用python实现命令模式的话,有一点有趣的是,你可以”执行”一个对象,就像执行一个函数一样,只要这个对象实现了 call 方法。
# 注意以下试图将撤销和重做打包成完整命令。classCommand(object): def__init__(self, do, undo): assert callable(do) and callable(undo) self.do = do self.undo = undo def__call__(self): self.do command = Command command# 试图定义一个宏classMacro(object): def__init__(self): self.__commands = defadd(self, command): self.__commands.append(command) def__call__(self): for command in self.__commands: command do = __call__ defundo(self): for command in reversed(self.__commands): command.undo
。
学习Java的同学注意了!!!
学习过程中遇到什么问题或者想获取学习资源的话,欢迎加入Java学习交流群,群号码:392216227我们一起学Java!