设计模式之命令模式

来源:互联网 发布:天音淘宝宝贝复制软件 编辑:程序博客网 时间:2024/06/05 10:52

命令模式

命令模式:将“请求”封装成对象,以便使用不同的请求,队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。
定义命令模式:
类图

今天我们讲解命令模式的模型就是遥控器,将遥控器的每个插槽,对应到一个命令这样就能让遥控器变成“调用者”。当按下按钮,相应命令对象的execute()方法就会被调用,其结果就是,接收者(例如:电灯、天花板电扇、音响)的动作被调用。就类似下面这个图:

实现遥控器:
package com.my.commond;public class RemoteControl {    //遥控器要处理7个开与关的命令,使用相应数组记录这些命令。    Command[] onCommands;    Command[] offCommands;    public RemoteControl(){        //实例化并初始化这两个开与关的数组。        onCommands = new Command[7];        offCommands = new Command[7];        Command noCommand = new NoCommand();        for(int i=0;i<7;i++){            onCommands[i] = noCommand;            offCommands[i] = noCommand;        }    }    public void setCommand(int slot,Command onCommand,Command offCommand){        //setCommand()方法有3个参数,分别是插槽的位置,开的命令、关的命令。这些命令将        //记录开关数组中对应的插槽位置。        onCommands[slot] = onCommand;        offCommands[slot] = offCommand;    }    public void onButtonWasPushed(int slot){        onCommands[slot].execute();    }    public void offButtonWasPushed(int slot){        offCommands[slot].execute();    }    public String toString(){        StringBuffer stringBuff = new StringBuffer();        stringBuff.append("\n---- Remote Control ----\n");        for(int i=0;i<onCommands.length;i++){            stringBuff.append("[slot "+i+"]"+onCommands[i].getClass().getName()            +"   "+offCommands[i].getClass().getName()+"\n");        }        return stringBuff.toString();    }}
实现命令:
电灯开关命令
package com.my.commond;public class LightOffCommand implements Command {    Light light;    public LightOffCommand(Light light){        this.light = light;    }    public void execute(){        light.off();    }    public void undo(){light.on();}}
音响开关命令
package com.my.commond;public class StereoOnWithCDCommand implements Command {    Stereo stereo;    public StereoOnWithCDCommand(Stereo stereo){        this.stereo = stereo;    }    public void execute(){        stereo.on();        stereo.setCD();        stereo.setVolume(11);    }}
测试遥控器:
package com.my.commond;public class RemoteLoader {    public static void main(String[] args){        RemoteControl remoteControl = new RemoteControl();        Light livingRoomLight = new Light("Living Room");        Light kitchenLight = new Light("Kitchen");        CeilingFan ceilingFan = new CeilingFan("Living Room");        GarageDoor garageDoor = new GarageDoor("");        Stereo stereo = new Stereo("Living Room");        //创建所有电灯命令对象        LightOnCommand livingRoomLightOn = new LightOnCommand(livingRoomLight);        LightOffCommand livingRoomLightOff = new LightOffCommand(livingRoomLight);        LightOnCommand kitchenLightOn = new LightOnCommand(kitchenLight);        LightOffCommand kitchenLightOff = new LightOffCommand(kitchenLight);        //创建吊扇的开与关        CeilingFanOnCommand ceilingFanOn = new CeilingFanOnCommand(ceilingFan);        CeilingFanOffCommand ceilingFanOff= new CeilingFanOffCommand(ceilingFan);        //创建车库门的上与下命令        GarageDoorUpCommand garageDoorUp = new GarageDoorUpCommand(garageDoor);        GarageDoorDownCommand garageDoorDown = new GarageDoorDownCommand(garageDoor);        //创建音响的开与关命令        StereoOnWithCDCommand stereoOnWithCD = new StereoOnWithCDCommand(stereo);        StereoOffCommand stereoOff = new StereoOffCommand(stereo);        remoteControl.setCommand(0,livingRoomLightOn,livingRoomLightOff);        remoteControl.setCommand(1,kitchenLightOn,kitchenLightOff);        remoteControl.setCommand(2,ceilingFanOn,ceilingFanOff);        remoteControl.setCommand(3,stereoOnWithCD,stereoOff);        System.out.println(remoteControl);        remoteControl.onButtonWasPushed(0);        remoteControl.offButtonWasPushed(0);        remoteControl.onButtonWasPushed(1);        remoteControl.offButtonWasPushed(1);        remoteControl.onButtonWasPushed(2);        remoteControl.offButtonWasPushed(2);        remoteControl.onButtonWasPushed(3);        remoteControl.offButtonWasPushed(3);    }}
run:

完善代码,以增加撤销功能:
package com.my.commond;public interface Command {    public void execute();    public void undo();//撤销方法}
开电灯
package com.my.commond;public class LightOnCommand implements Command {    Light light;    public LightOnCommand(Light light){        this.light = light;    }    public void execute(){        light.on();    }    public void undo(){light.off();}}
关电灯
package com.my.commond;public class LightOffCommand implements Command {    Light light;    public LightOffCommand(Light light){        this.light = light;    }    public void execute(){        light.off();    }    public void undo(){light.on();}}
package com.my.commond;public class RemoteControlWithUndo {    //遥控器要处理7个开与关的命令,使用相应数组记录这些命令。    Command[] onCommands;    Command[] offCommands;    Command undoCommand;    public RemoteControlWithUndo(){        //实例化并初始化这两个开与关的数组。        onCommands = new Command[7];        offCommands = new Command[7];        Command noCommand = new NoCommand();        for(int i=0;i<7;i++){            onCommands[i] = noCommand;            offCommands[i] = noCommand;        }        undoCommand = noCommand;    }    public void setCommand(int slot,Command onCommand,Command offCommand){        //setCommand()方法有3个参数,分别是插槽的位置,开的命令、关的命令。这些命令将        //记录开关数组中对应的插槽位置。        onCommands[slot] = onCommand;        offCommands[slot] = offCommand;    }    //按下按钮时,将命令记录在undoCommand实例变量中。    public void onButtonWasPushed(int slot){        onCommands[slot].execute();        undoCommand = onCommands[slot];    }    //按下按钮时,将命令记录在undoCommand实例变量中。    public void offButtonWasPushed(int slot){        offCommands[slot].execute();        undoCommand = offCommands[slot];    }    //当按下撤销按钮,调用undoCommand实例变量的undo()方法    public void undoButtonWasPushed(){        undoCommand.undo();    }}
run:
Living Room light  on Living Room light  off ---- Remote Control ----[slot 0]com.my.commond.LightOnCommand   com.my.commond.LightOffCommand[slot 1]com.my.commond.NoCommand   com.my.commond.NoCommand[slot 2]com.my.commond.NoCommand   com.my.commond.NoCommand[slot 3]com.my.commond.NoCommand   com.my.commond.NoCommand[slot 4]com.my.commond.NoCommand   com.my.commond.NoCommand[slot 5]com.my.commond.NoCommand   com.my.commond.NoCommand[slot 6]com.my.commond.NoCommand   com.my.commond.NoCommandLiving Room light  on Living Room light  off Living Room light  on ---- Remote Control ----[slot 0]com.my.commond.LightOnCommand   com.my.commond.LightOffCommand[slot 1]com.my.commond.NoCommand   com.my.commond.NoCommand[slot 2]com.my.commond.NoCommand   com.my.commond.NoCommand[slot 3]com.my.commond.NoCommand   com.my.commond.NoCommand[slot 4]com.my.commond.NoCommand   com.my.commond.NoCommand[slot 5]com.my.commond.NoCommand   com.my.commond.NoCommand[slot 6]com.my.commond.NoCommand   com.my.commond.NoCommandLiving Room light  off 
命令模式的应用场景:当需要将发出请求的对象和执行请求的对象解耦的时候,使用命令模式。
宏命令是命令的一种简单的延伸,允许调用多个命令。宏方法也可以支持撤销,这里我就不介绍宏命令,有兴趣的话大家可以查一下命令模式中的宏命令。
下回我们来一起学习适配器模式。

原创粉丝点击