参考:
- headfirst设计模式
你接到一个项目,做一个控制遥控器,可以控制家里所有电器,灯,冰箱,空调,热水器等等。遥控器的生产厂家已经和这些家居的厂商谈好了,他们提供了每个家居的控制方法,一个java的class,现在只有简单的开关功能。你要做的是在一个遥控器上可以控制所有家居。
嗯,现在你看到了一些基本的说明文档,各个家居的控制类:
要做这样的一个遥控器,你不会傻到使用if语句去判断每次按钮按下的是什么吧。
if(开灯){
light.on();
}else if(开电视){
tv.open();
}
万一有新的家居进来,你就要不停的修改这个方法,对开闭原则来说,真是够呛,而且维护起来很麻烦啊。
这个时候就可以使用命令模式,它可以将“动作的请求者”从“动作的执行者”对象中解耦。
怎么理解这句话呢?如果按照最开始的设计,动作请求者,遥控器的按钮,和对象的执行者light,tv,等都是在一起的(一个方法中被调用。在一起就说明是耦合)。你必须知道按下了那个按钮,然后找到对应的tv或者light,调用他们的方法。但是命令模式就是要解决这个,也就是将按钮和具体的执行light.on()方法分离。
具体怎么做
在这个设计中,采用“命令对象”就可以办到。利用命令对象,把请求封装成一个特定的对象,比如打开灯这个请求。新建一个对象,调用light的on方法,所以这个命令对象就要有这个light的引用。
那么当按下遥控器的开关时,我们只需要调用这个命令对象来做相应的工作就可以了。这样遥控器就和light解耦了。
来点代码
还记得oo设计的思想吗?是面向接口编程而不是面向实现编程。 接口或者abstract。
那么首先应该想到要有一个接口,怎么把这个接口找出来呢?
前面我们想到要有一个命令对象,使用命令对象去调用具体的家居,而遥控器只需要使用命令对象做相关的操作就可以了。为了解耦。
遥控器的每个按钮都是一个操作控制器controller,这个控制器一定是持有命令对象的引用,而命令对象持有具体的家居。所以他们才能够一级一级的调用。
既然遥控器不需要知道具体的命令对象是啥,那么这个引用就可以用接口代替了,所以命令对象都应该实现一个接口。
public interface Command {
public void execute();
}
既然有了接口,就来实现以下某个具体的命令对象,比如灯具的开关对象。
先要有light,厂家就提供了开和关。
public class Light {
public void on(){
System.out.println("开灯");
}
public void off(){
System.out.println("关灯");
}
}
再来一个命令对象,持有电灯对象。调用她的开关。
public class LightCommand implements Command {
Light light;
public LightCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.on();
}
}
然后来实现遥控器的按钮,持有接口,调用接口的方法,从而与具体的light解耦。
public class LightController {
Command command;
public LightController(){}
public void setCommand(Command command) {
this.command = command;
}
public void button(){
command.execute();
}
}
测试:
@Test
public void test(){
Light light = new Light();
LightCommand command = new LightCommand(light);
LightController controller = new LightController();
controller.setCommand(command);
controller.button();
// 自己实现一个车库的方法吧。
GarageDoor door = new GarageDoor();
GarageDoorCommand command1 = new GarageDoorCommand(door);
controller.setCommand(command1);
controller.button();
}
打印:
开灯
up
在测试中,只需要更换command,就可以实现对具体家居的控制了。
命令模式: 命令模式是为了解决命令的请求者和命令的实现者之间的耦合关系。命令模式是对功能方法的抽象,并不是对对象的抽象。