当前位置:首页>编程知识库>后端开发知识>设计模式是什么鬼(命令模式)
设计模式是什么鬼(命令模式)
阅读 1
2018-12-31
Java知音”,选择“置顶公众号”
技术文章第一时间送达!

//本文作者:凸凹里歐

//本文收录菜单栏:《设计模式是什么鬼》专栏中

命令模式,通常指的是一个对象向另一个对象发送信息指令的行为模型,比如父母命令孩子写作业、将军命令士兵进攻等。我们经过分析拆解方法会得到三个模块,首先得有命令发送方,接着是被传递的命令本身,最后就是命令的接收执行方了。那么,这样拆解到底有什么好处?让我们先来看一个最简单的例子,电灯泡。
既然是电灯那一定对应通电和断电的行为接口了,两个接口方法互斥,我们就叫它Switchable吧。
1public%20interface%20Switchable%20%7B//%E7%94%B5%E5%99%A8%E6%8E%A5%E5%8F%A3%0A2%20%20%20%20//%E9%80%9A%E7%94%B5%0A3%20%20%20%20public%20void%20on();%0A4%20%20%20%20//%E6%96%AD%E7%94%B5%0A5%20%20%20%20public%20void%20off();%0A6%0A7%7D%0A
对于具体的灯泡实现类,必然是通电亮,断电灭。
%201public%20class%20Bulb%20implements%20Switchable%20%7B%0A%202%0A%203%20%20%20%20@Override%0A%204%20%20%20%20public%20void%20on()%7B%0A%205%20%20%20%20%20%20%20%20System.out.println(%22%E9%80%9A%E7%94%B5%EF%BC%8C%E7%81%AF%E4%BA%AE%E3%80%82%22);%0A%206%20%20%20%20%7D%20%20%20%0A%207%0A%208%20%20%20%20@Override%0A%209%20%20%20%20public%20void%20off()%7B%0A10%20%20%20%20%20%20%20%20System.out.println(%22%E6%96%AD%E7%94%B5%EF%BC%8C%E7%81%AF%E7%81%AD%E3%80%82%22);%0A11%20%20%20%20%7D%0A12%0A13%7D%0A
同样地,我们再增加一个设备,如果是风扇的话则是通电转,断电停。
%201public%20class%20Fan%20implements%20Switchable%7B%0A%202%0A%203%20%20%20%20@Override%0A%204%20%20%20%20public%20void%20on()%20%7B%0A%205%20%20%20%20%20%20%20%20System.out.println(%22%E9%80%9A%E7%94%B5%EF%BC%8C%E9%A3%8E%E6%89%87%E8%BD%AC%E5%8A%A8%E3%80%82%22);%0A%206%20%20%20%20%7D%0A%207%0A%208%20%20%20%20@Override%0A%209%20%20%20%20public%20void%20off()%20%7B%0A10%20%20%20%20%20%20%20%20System.out.println(%22%E6%96%AD%E7%94%B5%EF%BC%8C%E9%A3%8E%E6%89%87%E5%81%9C%E6%AD%A2%E3%80%82%22);%0A11%20%20%20%20%7D%0A12%0A13%7D%0A
我们该如何操作呢?来吧,直接用电线接通电源。
%201public%20class%20Client%20%7B%0A%202%0A%203%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%204%0A%205%20%20%20%20%20%20%20%20System.out.println(%22===%E5%AE%A2%E6%88%B7%E7%AB%AF%E7%94%A8%E3%80%90%E7%94%B5%E7%BA%BF%E3%80%91%E7%9B%B4%E6%8E%A5%E6%93%8D%E4%BD%9C%E7%81%AF%E6%B3%A1===%22);%0A%206%20%20%20%20%20%20%20%20Bulb%20bulb%20=%20new%20Bulb();%0A%207%20%20%20%20%20%20%20%20bulb.on();%0A%208%20%20%20%20%20%20%20%20bulb.off();%0A%209%20%20%20%20%20%20%20%20/*%E6%89%93%E5%8D%B0%E8%BE%93%E5%87%BA%EF%BC%9A%0A10%20%20%20%20%20%20%20%20%20%20%20%20===%E5%AE%A2%E6%88%B7%E7%AB%AF%E7%94%A8%E3%80%90%E7%94%B5%E7%BA%BF%E3%80%91%E7%9B%B4%E6%8E%A5%E6%93%8D%E4%BD%9C%E7%81%AF%E6%B3%A1===%0A11%20%20%20%20%20%20%20%20%20%20%20%20%E9%80%9A%E7%94%B5%EF%BC%8C%E7%81%AF%E4%BA%AE%E3%80%82%0A12%20%20%20%20%20%20%20%20%20%20%20%20%E6%96%AD%E7%94%B5%EF%BC%8C%E7%81%AF%E7%81%AD%E3%80%82%20%0A13%20%20%20%20%20%20%20%20*/%0A14%20%20%20%20%7D%0A15%0A16%7D%0A
也许用户是个糙人,直接用导线给通电了,简单粗暴,虽然没有错,但这看上去与设计模式没有任何瓜葛。为了体现出模式的优越性,我们需要让系统进化得更高级一些,于是我们决定加入另一个模块,开关控制。
%201public%20class%20Switcher%20%7B%0A%202%0A%203%20%20%20%20//%20%E6%AD%A4%E5%BC%80%E5%85%B3%E4%B8%8E%E7%81%AF%E8%80%A6%E5%90%88%EF%BC%8C%E6%97%A0%E6%B3%95%E6%9B%BF%E6%8D%A2%E4%B8%BA%E5%85%B6%E4%BB%96%E7%94%B5%E5%99%A8%E3%80%82%0A%204%20%20%20%20//%20private%20Bulb%20bulb%20=%20new%20Bulb();%0A%205%0A%206%20%20%20%20//%20%E6%AD%A4%E5%BC%80%E5%85%B3%E4%B8%8E%E7%94%B5%E5%99%A8%E6%8E%A5%E5%8F%A3%E8%80%A6%E5%90%88%EF%BC%8C%E5%8F%AF%E4%BB%BB%E6%84%8F%E6%9B%BF%E6%8D%A2%E7%94%B5%E5%99%A8%E3%80%82%0A%207%20%20%20%20private%20Switchable%20switchable;%0A%208%0A%209%20%20%20%20//%20%E6%9B%BF%E6%8D%A2%E7%94%B5%E5%99%A8%E6%96%B9%E6%B3%95%0A10%20%20%20%20public%20void%20setSwitchable(Switchable%20switchable)%20%7B%0A11%20%20%20%20%20%20%20%20this.switchable%20=%20switchable;%0A12%20%20%20%20%7D%0A13%0A14%20%20%20%20//%20%E6%8C%89%E9%94%AE%E4%BA%8B%E4%BB%B6%E7%BB%91%E5%AE%9A%0A15%0A16%20%20%20%20//%20%E6%8C%89%E9%92%AE%E2%80%9C%E5%BC%80%E2%80%9D%E6%8C%89%E4%B8%8B%0A17%20%20%20%20public%20void%20buttonOnClick()%20%7B%0A18%20%20%20%20%20%20%20%20System.out.println(%22%E6%8C%89%E4%B8%8B%E5%BC%80%E2%80%A6%E2%80%A6%22);%0A19%20%20%20%20%20%20%20%20switchable.on();%0A20%20%20%20%20%7D%0A21%0A22%20%20%20%20//%20%E6%8C%89%E9%92%AE%E2%80%9C%E5%85%B3%E2%80%9D%E6%8C%89%E4%B8%8B%0A23%20%20%20%20public%20void%20buttonOffClick()%20%7B%0A24%20%20%20%20%20%20%20%20System.out.println(%22%E6%8C%89%E4%B8%8B%E5%85%B3%E2%80%A6%E2%80%A6%22);%0A25%20%20%20%20%20%20%20%20switchable.off();%0A26%20%20%20%20%7D%0A27%0A28%7D%0A
这里的开关就类似一个控制器了,有“开”和“关”两个按键分别绑定了设备的“通电”与“断电”行为方法。需要特别注意的是,如果在第4行我们声明地是灯泡,那么无疑这个开关与灯泡就绑定死了,也就是强耦合了,所以第7行我们声明的是Switchable接口引用,并提供第10行的替换电器方法给外界注入任何的设备。好了,我们换个方式运行程序。
%201public%20class%20Client%20%7B%0A%202%0A%203%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%204%0A%205%20%20%20%20%20%20%20%20System.out.println(%22===%E5%AE%A2%E6%88%B7%E7%AB%AF%E7%94%A8%E3%80%90%E5%BC%80%E5%85%B3%E3%80%91%E6%93%8D%E4%BD%9C%E7%94%B5%E5%99%A8===%22);%0A%206%20%20%20%20%20%20%20%20Switcher%20switcher%20=%20new%20Switcher();%0A%207%0A%208%20%20%20%20%20%20%20%20switcher.setSwitchable(new%20Bulb());//%E7%81%AF%E6%B3%A1%E6%8E%A5%E5%85%A5%E5%BC%80%E5%85%B3%E3%80%82%0A%209%20%20%20%20%20%20%20%20switcher.buttonOnClick();%0A10%20%20%20%20%20%20%20%20switcher.buttonOffClick();%0A11%20%20%20%20%20%20%20%20switcher.setSwitchable(new%20Fan());//%E9%A3%8E%E6%89%87%E6%8E%A5%E5%85%A5%E5%BC%80%E5%85%B3%E3%80%82%0A12%20%20%20%20%20%20%20%20switcher.buttonOnClick();%0A13%20%20%20%20%20%20%20%20switcher.buttonOffClick();%0A14%0A15%20%20%20%20%20%20%20%20/*%E6%89%93%E5%8D%B0%E8%BE%93%E5%87%BA%EF%BC%9A%0A16%20%20%20%20%20%20%20%20%20%20%20%20===%E5%AE%A2%E6%88%B7%E7%AB%AF%E7%94%A8%E3%80%90%E5%BC%80%E5%85%B3%E3%80%91%E6%93%8D%E4%BD%9C%E7%94%B5%E5%99%A8===%0A17%20%20%20%20%20%20%20%20%20%20%20%20%E6%8C%89%E4%B8%8B%E5%BC%80%E2%80%A6%E2%80%A6%0A18%20%20%20%20%20%20%20%20%20%20%20%20%E9%80%9A%E7%94%B5%EF%BC%8C%E7%81%AF%E4%BA%AE%E3%80%82%0A19%20%20%20%20%20%20%20%20%20%20%20%20%E6%8C%89%E4%B8%8B%E5%85%B3%E2%80%A6%E2%80%A6%0A20%20%20%20%20%20%20%20%20%20%20%20%20%E6%96%AD%E7%94%B5%EF%BC%8C%E7%81%AF%E7%81%AD%E3%80%82%0A21%20%20%20%20%20%20%20%20%20%20%20%20%E6%8C%89%E4%B8%8B%E5%BC%80%E2%80%A6%E2%80%A6%0A22%20%20%20%20%20%20%20%20%20%20%20%20%E9%80%9A%E7%94%B5%EF%BC%8C%E9%A3%8E%E6%89%87%E8%BD%AC%E5%8A%A8%E3%80%82%0A23%20%20%20%20%20%20%20%20%20%20%20%20%E6%8C%89%E4%B8%8B%E5%85%B3%E2%80%A6%E2%80%A6%0A24%20%20%20%20%20%20%20%20%20%20%20%20%E6%96%AD%E7%94%B5%EF%BC%8C%E9%A3%8E%E6%89%87%E5%81%9C%E6%AD%A2%E3%80%82%0A25%20%20%20%20%20%20%20%20%20*/%0A26%20%20%20%20%7D%0A27%0A28%7D%0A
这次看上去功能强大多了,开关可以随意地接入灯泡或者风扇,注入的是谁那么开关按钮直接就作用于谁,对于设备我们还可以继续扩展,设计模式开始体现优势了。等等,这个模式好像似曾相识的感觉,没错,这正是之前讲过的策略模式,可这跟命令模式有什么关系?不要着急,我们先看下这个开关策略模式是否满足了我们的需求。
假设我们的设备不断扩展,比如有了电视机,收音机等等设备,它们不止是开关通电这种简单行为模式了,还可以有转换频道、变音量等等更多的行为。
那么我们的简单开关还能满足对接电视机的琳琅满目的功能吗?注意之前我们的开关Switcher类中第7行代码:private Switchable switchable; 虽然可以替换设备,但只能是Switchable设备对象,这就与”可开关设备接口“强耦合了,也就是说它只能控制“灯泡或风扇”,并不能控制”电视或收音机”。
同时另一端我们的开关控制器也在不断进化,发展出了更多功能控制器、无线遥控器、甚至是手机App控制。
所以,如何把控制器与设备完全给拆解开势在必行,此时命令模式粉墨登场。现在我们得新定义出一组”命令“模块把控制器(发令者)与设备(执行者)彻底解耦,就以电视机和遥控器举例说明吧。
%201public%20interface%20Device%20extends%20Switchable%7B%0A%202%0A%203%20%20%20%20//%20%E9%A2%91%E9%81%93 %0A%204%20%20%20%20public%20void%20channelUp();%0A%205%20%20%20%20//%20%E9%A2%91%E9%81%93-%0A%206%20%20%20%20public%20void%20channelDown();%0A%207%20%20%20%20//%20%E9%9F%B3%E9%87%8F %0A%208%20%20%20%20public%20void%20volumeUp();%0A%209%20%20%20%20//%20%E9%9F%B3%E9%87%8F-%0A10%20%20%20%20public%20void%20volumeDown();%0A11%0A12%7D%0A
注意代码第1行的接口继承,我们的高级设备接口则遗传了之前的简单通断电接口,并新增了调节频道和音量4个功能。接下来是电视机与收音机实现类。
%201public%20class%20TV%20implements%20Device%20%7B%0A%202%0A%203%20%20%20%20@Override%0A%204%20%20%20%20public%20void%20on()%7B%0A%205%20%20%20%20%20%20%20%20System.out.println(%22%E7%94%B5%E8%A7%86%E6%9C%BA%E5%90%AF%E5%8A%A8%22);%0A%206%20%20%20%20%7D%20%20%20%0A%207%0A%208%20%20%20%20@Override%0A%209%20%20%20%20public%20void%20off()%7B%0A10%20%20%20%20%20%20%20%20System.out.println(%22%E7%94%B5%E8%A7%86%E6%9C%BA%E5%85%B3%E9%97%AD%22);%0A11%20%20%20%20%7D%0A12%0A13%20%20%20%20@Override%0A14%20%20%20%20public%20void%20channelUp()%20%7B%0A15%20%20%20%20%20%20%20%20System.out.println(%22%E7%94%B5%E8%A7%86%E6%9C%BA%E9%A2%91%E9%81%93 %22);%0A16%20%20%20%20%7D%0A17%0A18%20%20%20%20@Override%0A19%20%20%20%20public%20void%20channelDown()%20%7B%0A20%20%20%20%20%20%20%20%20System.out.println(%22%E7%94%B5%E8%A7%86%E6%9C%BA%E9%A2%91%E9%81%93-%22);%0A21%20%20%20%20%7D%0A22%0A23%20%20%20%20@Override%0A24%20%20%20%20public%20void%20volumeUp()%20%7B%0A25%20%20%20%20%20%20%20%20System.out.println(%22%E7%94%B5%E8%A7%86%E6%9C%BA%E9%9F%B3%E9%87%8F %22);%0A26%20%20%20%20%7D%0A27%0A28%20%20%20%20@Override%0A29%20%20%20%20public%20void%20volumeDown()%20%7B%0A30%20%20%20%20%20%20%20%20System.out.println(%22%E7%94%B5%E8%A7%86%E6%9C%BA%E9%9F%B3%E9%87%8F-%22);%0A31%20%20%20%20%7D%0A32%7D
%201public%20class%20Radio%20implements%20Device%20%7B%0A%202%0A%203%20%20%20%20@Override%0A%204%20%20%20%20public%20void%20on()%7B%0A%205%20%20%20%20%20%20%20%20System.out.println(%22%E6%94%B6%E9%9F%B3%E6%9C%BA%E5%90%AF%E5%8A%A8%22);%0A%206%20%20%20%20%7D%20%20%20%0A%207%0A%208%20%20%20%20@Override%0A%209%20%20%20%20public%20void%20off()%7B%0A10%20%20%20%20%20%20%20%20System.out.println(%22%E6%94%B6%E9%9F%B3%E6%9C%BA%E5%85%B3%E9%97%AD%22);%0A11%20%20%20%20%7D%0A12%0A13%20%20%20%20@Override%0A14%20%20%20%20public%20void%20channelUp()%20%7B%0A15%20%20%20%20%20%20%20%20System.out.println(%22%E6%94%B6%E9%9F%B3%E6%9C%BA%E8%B0%83%E9%A2%91 %22);%0A16%20%20%20%20%7D%0A17%0A18%20%20%20%20@Override%0A19%20%20%20%20public%20void%20channelDown()%20%7B%0A20%20%20%20%20%20%20%20%20System.out.println(%22%E6%94%B6%E9%9F%B3%E6%9C%BA%E8%B0%83%E9%A2%91-%22);%0A21%20%20%20%20%7D%0A22%0A23%20%20%20%20@Override%0A24%20%20%20%20public%20void%20volumeUp()%20%7B%0A25%20%20%20%20%20%20%20%20System.out.println(%22%E6%94%B6%E9%9F%B3%E6%9C%BA%E9%9F%B3%E9%87%8F %22);%0A26%20%20%20%20%7D%0A27%0A28%20%20%20%20@Override%0A29%20%20%20%20public%20void%20volumeDown()%20%7B%0A30%20%20%20%20%20%20%20%20System.out.println(%22%E6%94%B6%E9%9F%B3%E6%9C%BA%E9%9F%B3%E9%87%8F-%22);%0A31%20%20%20%20%7D%0A32%7D%0A
没什么好说的,下来是解耦的重点了,我们在策略模式的基础上又增加一层中间模块,开始编写命令模块代码,首先是命令接口。
1public%20interface%20Command%20%7B%0A2%0A3%20%20%20%20//%E6%89%A7%E8%A1%8C%E5%91%BD%E4%BB%A4%E6%93%8D%E4%BD%9C%0A4%20%20%20%20public%20void%20exe();%0A5%0A6%20%20%20%20//%E5%8F%8D%E6%89%A7%E8%A1%8C%E5%91%BD%E4%BB%A4%E6%93%8D%E4%BD%9C%0A7%20%20%20%20public%20void%20unexe();%0A8%0A9%7D%0A
命令接口有执行操作与反执行操作两个标准功能,然后定义其命令实现类,开关机命令、频道转换命令、以及音量调节命令。
%201public%20class%20SwitchCommand%20implements%20Command%20%7B%0A%202%0A%203%20%20%20%20private%20Device%20device;//%20%E6%AD%A4%E5%A4%84%E6%8C%81%E6%9C%89%E9%AB%98%E7%BA%A7%E8%AE%BE%E5%A4%87%E6%8E%A5%E5%8F%A3%E3%80%82%0A%204%0A%205%20%20%20%20public%20SwitchCommand(Device%20device)%20%7B%0A%206%20%20%20%20%20%20%20%20this.device%20=%20device;%0A%207%20%20%20%20%7D%0A%208%0A%209%20%20%20%20@Override%0A10%20%20%20%20public%20void%20exe()%20%7B%0A11%20%20%20%20%20%20%20%20device.on();//%20%E6%89%A7%E8%A1%8C%E5%91%BD%E4%BB%A4%E8%B0%83%E7%94%A8%E5%BC%80%E6%9C%BA%E6%93%8D%E4%BD%9C%0A12%20%20%20%20%7D%0A13%0A14%20%20%20%20@Override%0A15%20%20%20%20public%20void%20unexe()%20%7B%0A16%20%20%20%20%20%20%20%20device.off();//%20%E5%8F%8D%E6%89%A7%E8%A1%8C%E5%91%BD%E4%BB%A4%E8%B0%83%E7%94%A8%E5%85%B3%E6%9C%BA%E6%93%8D%E4%BD%9C%0A17%20%20%20%20%7D%0A18%0A19%7D
%201public%20class%20ChannelCommand%20implements%20Command%7B%0A%202%0A%203%20%20%20%20private%20Device%20device;%0A%204%0A%205%20%20%20%20public%20ChannelCommand(Device%20device)%20%7B%0A%206%20%20%20%20%20%20%20%20this.device%20=%20device;%0A%207%20%20%20%20%7D%0A%208%0A%209%20%20%20%20@Override%0A10%20%20%20%20public%20void%20exe()%20%7B%0A11%20%20%20%20%20%20%20%20device.channelUp();%0A12%20%20%20%20%7D%0A13%0A14%20%20%20%20@Override%0A15%20%20%20%20public%20void%20unexe()%20%7B%0A16%20%20%20%20%20%20%20%20device.channelDown();%0A17%20%20%20%20%7D%0A18%0A19%7D
%201public%20class%20VolumeCommand%20implements%20Command%7B%0A%202%0A%203%20%20%20%20private%20Device%20device;%0A%204%0A%205%20%20%20%20public%20VolumeCommand(Device%20device)%20%7B%0A%206%20%20%20%20%20%20%20%20this.device%20=%20device;%0A%207%20%20%20%20%7D%0A%208%0A%209%20%20%20%20@Override%0A10%20%20%20%20public%20void%20exe()%20%7B%0A11%20%20%20%20%20%20%20%20device.volumeUp();%0A12%20%20%20%20%7D%0A13%0A14%20%20%20%20@Override%0A15%20%20%20%20public%20void%20unexe()%20%7B%0A16%20%20%20%20%20%20%20%20device.volumeDown();%0A17%20%20%20%20%7D%0A18%0A19%7D%0A
代码很简单,但是系统模组相对复杂,所以一定要搞清楚各模块间关系再继续。最后一个模块是遥控器类,也就是命令发送方了。我们保持简单,遥控器集成了OK按键以及上下左右方向键。
%201public%20class%20Controller%20%7B%0A%202%20%20%20%20private%20Command%20okCommand;%0A%203%20%20%20%20private%20Command%20verticalCommand;%0A%204%20%20%20%20private%20Command%20horizontalCommand;%0A%205%0A%206%20%20%20%20//%20%E7%BB%91%E5%AE%9AOK%E9%94%AE%E5%91%BD%E4%BB%A4%0A%207%20%20%20%20public%20void%20bindOKCommand(Command%20okCommand)%20%7B%0A%208%20%20%20%20%20%20%20%20this.okCommand%20=%20okCommand;%0A%209%20%20%20%20%7D%0A10%0A11%20%20%20%20//%20%E7%BB%91%E5%AE%9A%E4%B8%8A%E4%B8%8B%E6%96%B9%E5%90%91%E9%94%AE%E5%91%BD%E4%BB%A4%0A12%20%20%20%20public%20void%20bindVerticalCommand(Command%20verticalCommand)%20%7B%0A13%20%20%20%20%20%20%20%20this.verticalCommand%20=%20verticalCommand;%0A14%20%20%20%20%7D%0A15%0A16%20%20%20%20//%20%E7%BB%91%E5%AE%9A%E5%B7%A6%E5%8F%B3%E6%96%B9%E5%90%91%E9%94%AE%E5%91%BD%E4%BB%A4%0A17%20%20%20%20public%20void%20bindHorizontalCommand(Command%20horizontalCommand)%20%7B%0A18%20%20%20%20%20%20%20%20this.horizontalCommand%20=%20horizontalCommand;%0A19%20%20%20%20%7D%0A20%0A21%20%20%20%20//%20%E5%BC%80%E5%A7%8B%E6%8C%89%E9%94%AE%E6%98%A0%E5%B0%84%E5%91%BD%E4%BB%A4%0A22%20%20%20%20public%20void%20buttonOKHold()%20%7B%0A23%20%20%20%20%20%20%20%20System.out.print(%22%E9%95%BF%E6%8C%89OK%E6%8C%89%E9%94%AE%E2%80%A6%E2%80%A6%22);%0A24%20%20%20%20%20%20%20%20okCommand.exe();%0A25%20%20%20%20%7D%0A26%0A27%20%20%20%20public%20void%20buttonOKClick()%20%7B%0A28%20%20%20%20%20%20%20%20System.out.print(%22%E5%8D%95%E5%87%BBOK%E6%8C%89%E9%94%AE%E2%80%A6%E2%80%A6%22);%0A29%20%20%20%20%20%20%20%20okCommand.unexe();%0A30%20%20%20%20%7D%0A31%0A32%20%20%20%20public%20void%20buttonUpClick()%20%7B%0A33%20%20%20%20%20%20%20%20System.out.print(%22%E5%8D%95%E5%87%BB%E2%86%91%E6%8C%89%E9%94%AE%E2%80%A6%E2%80%A6%22);%0A34%20%20%20%20%20%20%20%20verticalCommand.exe();%0A35%20%20%20%20%7D%0A36%0A37%20%20%20%20public%20void%20buttonDownClick()%20%7B%0A38%20%20%20%20%20%20%20%20System.out.print(%22%E5%8D%95%E5%87%BB%E2%86%93%E6%8C%89%E9%94%AE%E2%80%A6%E2%80%A6%22);%0A39%20%20%20%20%20%20%20%20verticalCommand.unexe();%0A40%20%20%20%20%7D%0A41%0A42%20%20%20%20public%20void%20buttonLeftClick()%20%7B%0A43%20%20%20%20%20%20%20%20System.out.print(%22%E5%8D%95%E5%87%BB%E2%86%90%E6%8C%89%E9%94%AE%E2%80%A6%E2%80%A6%22);%0A44%20%20%20%20%20%20%20%20horizontalCommand.unexe();%0A45%20%20%20%20%7D%0A46%0A47%20%20%20%20public%20void%20buttonRightClick()%20%7B%0A48%20%20%20%20%20%20%20%20System.out.print(%22%E5%8D%95%E5%87%BB%E2%86%92%E6%8C%89%E9%94%AE%E2%80%A6%E2%80%A6%22);%0A49%20%20%20%20%20%20%20%20horizontalCommand.exe();%0A50%20%20%20%20%7D%0A51%7D%0A
这个遥控器持有三个命令组件,并且于第7行开始定义命令绑定方法,最后从第22行开始定义各按键触发方法并映射到相应的命令操作上。可以看到,控制器对设备一无所知,也就是它上面不再绑定有任何设备了,而是只绑定命令。最后,客户端又换了一种方式运行程序。
%201public%20class%20Client%20%7B%0A%202%0A%203%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%204%20%20%20%20%20%20%20%20System.out.println(%22===%E5%AE%A2%E6%88%B7%E7%AB%AF%E7%94%A8%E3%80%90%E5%8F%AF%E7%BC%96%E7%A8%8B%E5%BC%8F%E9%81%A5%E6%8E%A7%E5%99%A8%E3%80%91%E6%93%8D%E4%BD%9C%E7%94%B5%E5%99%A8===%22);%0A%205%20%20%20%20%20%20%20%20Device%20tv%20=%20new%20TV();%0A%206%20%20%20%20%20%20%20%20Device%20radio%20=%20new%20Radio();%0A%207%20%20%20%20%20%20%20%20Controller%20controller%20=%20new%20Controller();%0A%208%0A%209%20%20%20%20%20%20%20%20//%E7%BB%91%E5%AE%9A%E3%80%90%E7%94%B5%E8%A7%86%E6%9C%BA%E3%80%91%E7%9A%84%E3%80%90%E5%91%BD%E4%BB%A4%E3%80%91%E5%88%B0%E3%80%90%E6%8E%A7%E5%88%B6%E5%99%A8%E6%8C%89%E9%94%AE%E3%80%91%0A10%20%20%20%20%20%20%20%20controller.bindOKCommand(new%20SwitchCommand(tv));%0A11%20%20%20%20%20%20%20%20controller.bindVerticalCommand(new%20ChannelCommand(tv));//%E4%B8%8A%E4%B8%8B%E8%B0%83%E5%8F%B0%0A12%20%20%20%20%20%20%20%20controller.bindHorizontalCommand(new%20VolumeCommand(tv));//%E5%B7%A6%E5%8F%B3%E8%B0%83%E9%9F%B3%0A13%0A14%20%20%20%20%20%20%20%20controller.buttonOKHold();%0A15%20%20%20%20%20%20%20%20controller.buttonUpClick();%0A16%20%20%20%20%20%20%20%20controller.buttonUpClick();%0A17%20%20%20%20%20%20%20%20controller.buttonDownClick();%0A18%20%20%20%20%20%20%20%20controller.buttonRightClick();%0A19%0A20%20%20%20%20%20%20%20%20/*%E6%89%93%E5%8D%B0%E8%BE%93%E5%87%BA%EF%BC%9A%0A21%20%20%20%20%20%20%20%20%20%20%20%20===%E5%AE%A2%E6%88%B7%E7%AB%AF%E7%94%A8%E3%80%90%E5%8F%AF%E7%BC%96%E7%A8%8B%E5%BC%8F%E9%81%A5%E6%8E%A7%E5%99%A8%E3%80%91%E6%93%8D%E4%BD%9C%E7%94%B5%E5%99%A8===%0A22%20%20%20%20%20%20%20%20%20%20%20%20%E9%95%BF%E6%8C%89OK%E6%8C%89%E9%94%AE%E2%80%A6%E2%80%A6%E7%94%B5%E8%A7%86%E6%9C%BA%E5%90%AF%E5%8A%A8%0A23%20%20%20%20%20%20%20%20%20%20%20%20%E5%8D%95%E5%87%BB%E2%86%91%E6%8C%89%E9%94%AE%E2%80%A6%E2%80%A6%E7%94%B5%E8%A7%86%E6%9C%BA%E9%A2%91%E9%81%93 %0A24%20%20%20%20%20%20%20%20%20%20%20%20%E5%8D%95%E5%87%BB%E2%86%91%E6%8C%89%E9%94%AE%E2%80%A6%E2%80%A6%E7%94%B5%E8%A7%86%E6%9C%BA%E9%A2%91%E9%81%93 %0A25%20%20%20%20%20%20%20%20%20%20%20%20%E5%8D%95%E5%87%BB%E2%86%93%E6%8C%89%E9%94%AE%E2%80%A6%E2%80%A6%E7%94%B5%E8%A7%86%E6%9C%BA%E9%A2%91%E9%81%93-%0A26%20%20%20%20%20%20%20%20%20%20%20%20%E5%8D%95%E5%87%BB%E2%86%92%E6%8C%89%E9%94%AE%E2%80%A6%E2%80%A6%E7%94%B5%E8%A7%86%E6%9C%BA%E9%9F%B3%E9%87%8F %0A27%20%20%20%20%20%20%20%20*/%0A28%0A29%20%20%20%20%20%20%20%20//%E7%BB%91%E5%AE%9A%E3%80%90%E6%94%B6%E9%9F%B3%E6%9C%BA%E3%80%91%E7%9A%84%E3%80%90%E5%91%BD%E4%BB%A4%E3%80%91%E5%88%B0%E3%80%90%E6%8E%A7%E5%88%B6%E5%99%A8%E6%8C%89%E9%94%AE%E3%80%91%0A30%20%20%20%20%20%20%20%20controller.bindOKCommand(new%20SwitchCommand(radio));%0A31%20%20%20%20%20%20%20%20controller.bindVerticalCommand(new%20VolumeCommand(radio));//%E4%B8%8A%E4%B8%8B%E8%B0%83%E9%9F%B3%0A32%20%20%20%20%20%20%20%20controller.bindHorizontalCommand(new%20ChannelCommand(radio));//%E5%B7%A6%E5%8F%B3%E8%B0%83%E5%8F%B0%0A33%0A34%20%20%20%20%20%20%20%20controller.buttonOKHold();%0A35%20%20%20%20%20%20%20%20controller.buttonUpClick();%0A36%20%20%20%20%20%20%20%20controller.buttonUpClick();%0A37%20%20%20%20%20%20%20%20controller.buttonRightClick();%0A38%20%20%20%20%20%20%20%20controller.buttonDownClick();%0A39%0A40%20%20%20%20%20%20%20%20/*%E6%89%93%E5%8D%B0%E8%BE%93%E5%87%BA%EF%BC%9A%0A41%20%20%20%20%20%20%20%20%20%20%20%20%E9%95%BF%E6%8C%89OK%E6%8C%89%E9%94%AE%E2%80%A6%E2%80%A6%E6%94%B6%E9%9F%B3%E6%9C%BA%E5%90%AF%E5%8A%A8%0A42%20%20%20%20%20%20%20%20%20%20%20%20%E5%8D%95%E5%87%BB%E2%86%91%E6%8C%89%E9%94%AE%E2%80%A6%E2%80%A6%E6%94%B6%E9%9F%B3%E6%9C%BA%E9%9F%B3%E9%87%8F %0A43%20%20%20%20%20%20%20%20%20%20%20%20%E5%8D%95%E5%87%BB%E2%86%91%E6%8C%89%E9%94%AE%E2%80%A6%E2%80%A6%E6%94%B6%E9%9F%B3%E6%9C%BA%E9%9F%B3%E9%87%8F %0A44%20%20%20%20%20%20%20%20%20%20%20%20%E5%8D%95%E5%87%BB%E2%86%92%E6%8C%89%E9%94%AE%E2%80%A6%E2%80%A6%E6%94%B6%E9%9F%B3%E6%9C%BA%E8%B0%83%E9%A2%91 %0A45%20%20%20%20%20%20%20%20%20%20%20%20%E5%8D%95%E5%87%BB%E2%86%93%E6%8C%89%E9%94%AE%E2%80%A6%E2%80%A6%E6%94%B6%E9%9F%B3%E6%9C%BA%E9%9F%B3%E9%87%8F-%0A46%20%20%20%20%20%20%20%20*/%0A47%0A48%20%20%20%20%7D%0A49%0A50%7D%0A
很显然,客户端可以肆意妄为地组装各个模块了,也就是说可以遥控电视,也可以遥控收音机,或许绑定上下键调音量,或许是换成左右键调音量,甚至可以定义一个宏命令去控制灯泡的切换开关实现一种霓虹灯闪烁的效果(读者可以思考怎样实现),而对于控制器端本身,同样可以继续扩展,或许干脆替换个游戏手柄或者键盘,一样可以发号施令。
至此,发令控制方与接受执行方完全被拆解开,这让我们实现了对各模块的自由扩展,对指令映射、设备绑定的灵活操控,松散的系统得以成就繁多模块解耦的最终目的。
以上数据来源于网络,如有侵权,请联系删除。
评论 (0)