命令模式(Command Pattern),将发出请求的对象和执行请求的对象解耦。在被解耦的两者之间是通过命令对象进行沟通。命令对象封装了接收者和一个或一组动作。
举个栗子:
需要设计一个遥控器,该遥控器具有3个可编程的插槽(每个都可以指定到一个不同的家电装置),第一个槽位对应电灯Light,第二个槽位风扇Fan,第三个槽位热水器Heater,每个插槽都有对应的开关按钮。这个遥控器还具备一个整体的撤销按钮(暂时支持一次撤销)。
分析:
有3个槽位,每个槽位都有开和关的情况,如果用一般的编程方式的话,我们要通过一堆的if语句去判断这3*2中情况。通过命令模式给出某个槽位对应的命令即可。
1、命令接口:
接口 Command.java 类:
/**
* 命令接口
*/
public interface Command {
public void execute();
}
2、设备相关类(与命令接口无关)
Light.java 类:
/**
* 设备:电灯
*/
public class Light{
public void on(){
System.out.println("Light is on!");
}
public void off(){
System.out.println("Light is off!");
}
}
Fan.java 类:
/**
* 设备:电风扇
*/
public class Fan {
public void on(){
System.out.println("Fan is on!");
}
public void off(){
System.out.println("Fan is off!");
}
}
Heater.java 类:
/**
* 设备:热水器
*/
public class Heater {
public void on(){
System.out.println("Heater is on!");
}
public void off(){
System.out.println("Heater is off!");
}
}
3、设备命令(需要实现commad)
NoCommand.java 类:
/**
* 命令:什么都不做命令
*/
public class NoCommand implements Command {
@Override
public void execute() {
System.out.println("Do no thing!");
}
}
LihgtCommanOn.java 类:
/**
* 命令: 电灯开启命令
*/
public class LightCommandOn implements Command {
private Light light;
public LightCommandOn(Light light){
this.light = light;
}
@Override
public void execute() {
light.on();
}
}
LightCommandOff.java 类:
/**
* 命令:电灯关闭命令
*/
public class LightCommandOff implements Command {
private Light light;
public LightCommandOff(Light light){
this.light = light;
}
@Override
public void execute() {
light.off();
}
}
FanCommandOn.java 类:
/**
* 命令:电风扇开启命令
*/
public class FanCommandOn implements Command {
private Fan fan;
public FanCommandOn(Fan fan){
this.fan = fan;
}
@Override
public void execute() {
fan.on();
}
}
FanCommandOff.java 类:
/**
* 命令:电风扇关闭命令
*/
public class FanCommandOff implements Command {
private Fan fan;
public FanCommandOff(Fan fan){
this.fan = fan;
}
@Override
public void execute() {
fan.off();
}
}
HeaterCommandOn.java 类:
/**
* 命令:热水器开启命令
*/
public class HeaterCommandOn implements Command {
private Heater heater;
public HeaterCommandOn(Heater heater){
this.heater = heater;
}
@Override
public void execute() {
heater.on();
}
}
HeaterCommandOff.java 类:
/**
* 命令:热水器关闭命令
*/
public class HeaterCommandOff implements Command {
private Heater heater;
public HeaterCommandOff(Heater heater){
this.heater = heater;
}
@Override
public void execute() {
heater.off();
}
}
分析:
这里有三组设备:电灯Light、电风扇Fan、热水器Heater,每个设备都有开和关的命令,因此需要编写6个设备相关的命令类,注意,每个设备命令类都要实现Command接口。4、遥控器
RemoteController.java 类:
/**
* 遥控器
*/
public class RemoteController {
Command[] commandsOn = new Command[3];
Command[] commandsOff = new Command[3];
Command noCommand = new NoCommand();
Command undoComman = new NoCommand();
/**
* 初始化
*/
public RemoteController(){
for(int i=0;i<3;i++){
commandsOn[i] = noCommand; //刚开始的命令都为空操作
commandsOff[i] = noCommand;
}
}
/**
* 将各个槽位分别设置对应的命令
* @param slot
* @param commandOn
* @param commandOff
*/
public void setCommand(int slot, Command commandOn, Command commandOff){
commandsOn[slot] = commandOn;
commandsOff[slot] = commandOff;
}
/**
* 某个槽位开启操作
* @param slot
*/
public void buttonPushOn(int slot){
commandsOn[slot].execute();
undoComman = commandsOff[slot];
}
/**
* 某个槽位关闭操作
* @param slot
*/
public void buttonPushOff(int slot){
commandsOff[slot].execute();
undoComman = commandsOn[slot];
}
/**
* 按钮按下,执行撤销操作
*/
public void buttonPushUndo(){
undoComman.execute();
}
}
5、实际调用的程序如下:
public static void main(String[] args) {
Light light = new Light();
LightCommandOn lightCommandOn = new LightCommandOn(light);
LightCommandOff lightCommandOff = new LightCommandOff(light);
Fan fan = new Fan();
FanCommandOn fanCommandOn = new FanCommandOn(fan);
FanCommandOff fanCommandOff = new FanCommandOff(fan);
Heater heater = new Heater();
HeaterCommandOn heaterCommandOn = new HeaterCommandOn(heater);
HeaterCommandOff heaterCommandOff = new HeaterCommandOff(heater);
RemoteController remoteController = new RemoteController();
remoteController.setCommand(0, lightCommandOn, lightCommandOff);
remoteController.setCommand(1, fanCommandOn, fanCommandOff);
remoteController.setCommand(2,heaterCommandOn,heaterCommandOff);
remoteController.buttonPushOn(1);
remoteController.buttonPushUndo();
remoteController.buttonPushOff(0);
remoteController.buttonPushUndo();
}
输出结果:
Fan is on!
Fan is off!
Light is off!
Light is on!
分析:
遥控器中提供了将不同的设备开关命令对应槽位的设置,并提供了撤销上一步的操作。实际调用的程序可以参考上面提供的demo。通过命令作为中间者,实现命令发起请求和命令接收者的解耦。