命令模式
需求
假设现在有一个智能遥控器,用来控制房间的一些电子产品。数字键0-9分别有不同的动作。
假如数字1,用来打开客厅电灯,数字2关闭客厅电灯。数字3打开卧室电灯,数字4关闭卧室电灯。数字5打开电视,数字6关闭电视。如果有这样一个需求,如何实现会比较简单呢。
分析
上述简述包含两种不同的对象。一是遥控器,用来操作对应的电子装置,二是电子装置,被遥控器操控。 先来定义这些电子装置:
/**
* 客厅电灯对象
**/
public class LivingRoomLight{
public void on(){//打开客厅电灯}
public void off(){//关闭客厅电灯}
}
/**
* 卧室电灯对象
**/
public class BedRoomLight{
public void on(){//打开卧室电灯}
public void off(){//关闭卧室电灯}
}
/**
* 电视对象
**/
public class Television{
public void on(){//打开电视}
public void off(){//关闭电视}
}
/**
* 遥控器
**/
public class Telecontroller {
private LivingRoomLight livingRoomLight = new LivingRoomLight();
private BedRoomLight bedRoomLight = new BedRoomLight();
private Television television = new Television();
public void buttonWasPressed(String btn){
if("btn1".equals(btn)){
livingRoomLight.on();
} else if("btn2".equals(btn)){
livingRoomLight.off();
} else if("btn3".equals(btn)){
bedRoomLight.on();
} else if("btn4".equals(btn)){
bedRoomLight.off();
} else if("btn5".equals(btn)){
television.on();
} else if("btn6".equals(btn)){
television.off();
}
}
}
/**
* 人,操作遥控器
**/
public class TelecontrollerTest {
Telecontroller telecontroller = new Telecontroller();
telecontroller.buttonWasPressed("btn3");
}
这是简易的一个遥控器,可以看到,遥控器严重依赖了执行者对象,设计模式原则为:依赖抽象而不依赖实际。这样依赖了具体类,给后期的扩展维护,带来极大的不便。例如:现在要给按钮7和8进行编程,实现控制电扇的动作。除了要增加电扇对象之外,还需要修改遥控器buttonWasPressed()方法。这样做是没有一点弹性的。
正好有一个模式:命令模式,可以解决这个问题。
命令模式
命令模式,将请求单独封装为一个对象,使请求者与执行者完美的进行了解耦。
创建命令对象
/**
* 命令抽象类
**/
public class Command{
void execute();
}
/**
* 打开电灯命令
**/
public class LivingRoomLightOnCommand implements Command{
LivingRoomLight livingRoomLight;
public LivingRoomLightOnCommand (LivingRoomLight livingRoomLight){
this.livingRoomLight = livingRoomLight;
}
public void execute(){
livingRoomLight.on();
}
}
/**
* 打开电视命令
**/
public class TelevisionOnCommand implements Command{
Television television;
public TelevisionOnCommand (Television television){
this.television= television;
}
public void execute(){
television.on();
}
}
/**
* 遥控器
**/
public class Telecontroller {
Command[] commands = new Command[8];
public void setCommands (int index, Command command){
commands[index] = command;
}
public void buttonWasPressed(int index){
commands[index].execute();
}
}
public class TelecontrollerTest {
public static void main(String[] args){
Telecontroller telecontroller = new TeleController();
telecontroller.setCommands(1, new Command(new LivingRoomLigntOnCommand(new LivingRoomLight())));
telecontroller.execute();
}
}
这样遥控器只依赖了抽象的命令对象,如果增加或者删除被执行对象,遥控器代码都不需要改变。更加富有弹性。
命令模式一般用于队列的执行等模块。目前暂时还没有用到过命令模式。