HeadFirst-设计模式-命令模式

版权声明:来这世间走一遭总的留下点什么 https://blog.csdn.net/FightingITPanda/article/details/80807236

命令模式:将请求封装成对象,使动作的请求者从动作的执行者对象中解耦,这可以让你使用不同的请求、队列,或者日志请求来参数化其他对象,。命令模式也可以支持撤销操作,是一种对象行为性模式。
这里写图片描述


话不多说:直接上实例:
下面我们来实现一个家电自动化遥控器的api,一个遥控器,双排按钮,控制一堆家电的开关的操作。就这么个事
这里写图片描述
差不多有这些厂家类:
这里写图片描述
1.先把它要的这些类写好

//灯
class  Light2{
    public String name ;
    public void on(){}
    public void off(){}
}
//天花板灯
class CeilingLight extends Light2{ 

    public CeilingLight(String name){
        this.name = name;
    }
    public void on(){
        System.out.println("已经为您打开天花板的灯。。");
    }
    public void off(){
        System.out.println("已经为您关上天花板的灯。。");
    }
    public void dim(){
        System.out.println("已经为您调暗天花板的灯。。");
    }
}
//室外灯
class OutDoorLight2 extends Light2{
    public void on(){
        System.out.println("正在为您打开室外灯。。");
    }
    public void off(){
        System.out.println("正在为您关闭室外灯。。");
    }
}
//花园灯
class GardenLight2 extends Light2{
    public void setDuskTime(){
        System.out.println("已经为您设置黄昏时间打开灯。。");
    }
    public void setDawnTime(){
        System.out.println("已经为您设置黎明时间关闭灯。。");
    }
}
//吊扇
class CeilingFan{
    public void high(){
        System.out.println("正在为您升高吊扇。。");
    }
    public void medium(){
        System.out.println("吊扇已为您调到适中位置。。");
    }
    public void low(){
        System.out.println("正在问您降低吊扇。。");
    }
    public void off(){
        System.out.println("已经为您关闭吊扇。。");
    }
    public void getSpeed(){
        System.out.println("正在为您将吊扇调到适宜位置。。");
    }
}
//洒水器
class Sprinkler{
    public void waterOn(){
        System.out.println("已经为您打开洒水器。。");
    }
    public void waterOff(){
        System.out.println("已经为您关闭洒水器。。");
    }
}
//电视
class TV{
    public void on(){
        System.out.println("已经为您打开电视。。");
    }
    public void off(){
        System.out.println("已经为您关闭电视。。");
    }
    public void setInputChannel(){
        System.out.println("正在为您选择频道。。");
    }
    public void setVolumn(){
        System.out.println("正在为您调节音量。。");
    }
}
//车库门
class GarageDoor{
    public void up(){
        System.out.println("正在为你生起车库门。。");
    }
    public void down(){
        System.out.println("正在为您关闭车库门。。");
    }
    public void stop(){
        System.out.println("正在为您固定车库门。。");
    }
    public void lightOn(){
        System.out.println("正在为您打开车库门的灯。。");
    }
    public void lightOff(){
        System.out.println("正在为您关闭车库门的灯。。");
    }
}

//应用控制
class ApplicationControl{
    public void on(){
        System.out.println("正在为您打开应用控制。。");
    }
    public void off(){
        System.out.println("正在为您关闭应用控制。。");
    }
}
//立体声
class Stereo2{
    public void on(){
        System.out.println("已经为您打开音响。。");
    }
    public void off(){
        System.out.println("已经为您关闭音响。。");
    }
    public void setCD(){
        System.out.println("已经为您放好CD光盘。。");
    }
    public void setDVD(){
        System.out.println("已经为您放好dvd光盘。。");
    }
    public void setVolume(){
        System.out.println("正在为您调节立体声音量。。");
    }
}
//水龙头控制
class FaucetControl{
    public void openValue(){
        System.out.println("正在为您打开水龙头。。");
    }
    public void closeValue(){
        System.out.println("正在为您关闭水龙头。。");
    }
}
//热水浴缸
class Hottub{
    public void circulate(){
        System.out.println("已经为您设置循环加热水。。");
    }
    public void jetsOn(){
        System.out.println("已经为您打开喷头。。");
    }
    public void jetsOff(){
        System.out.println("已经为您关闭喷头。。");
    }
    public void setTemperature(){
        System.out.println("正在为您调节适宜水温。。");
    }
}
//恒温器
class Thermostat{
    public void setTemperature(){
        System.out.println("已经为您调好温度。。");
    }
}
//安全控制
class SecurityControl{
    public void arm(){

    }
    public void disarm(){

    }
}

遥控器是请求者,请求执行如上操作,家电是执行者,执行具体开关等操作,现在把请求命令拿出来封装成对象,所以我们提供一个命令接口Command2,遥控器只管去调命令接口的execute()方法,其他的不管,执行者就是你调我execute()我就执行我的操作,其他不管,请求者遥控器和执行者家电不会直接交互,达到解耦。
2.把命令拿出来封装,提供execute()对外接口,

//公共命令接口-执行命令方法
interface Command2{
    public void execute();//执行
    public void undo();//撤销
}
//啥也不做命令  
class NoCommand2 implements Command2{
    public void execute(){
        System.out.println("啥也不做命令哦。。");
    }
    public void undo(){
        System.out.println("啥也没撤销。。");
    }
}

3.再来实现具体电器的开、关命令

//打开电灯命令
class LightOnCommand2 implements Command2{
    Light2 light1;
    public LightOnCommand2(Light2 light){//可传所有灯对象
        this.light1 = light;
    }
    public void execute(){
        light1.on();
    }
    public void undo(){
        light1.off();
    }
}
//关闭电灯命令
class LightOffCommand2 implements Command2{
    Light2 light;
    public LightOffCommand2(Light2 light){
        this.light = light;
    }
    public void execute(){
        light.off();
    }
    public void undo(){
        light.on();
    }
}
//打开车库门命令
class GarageDoorOpenCommand implements Command2{
    GarageDoor door;
    public  GarageDoorOpenCommand(GarageDoor door){//不写有参构造还不行,的给door一个new好的对象,不然door.up()会报错 空指针,都没对象呢,调啥方法
        this.door = door;
    }
    public void execute(){
        door.up();
    }
    public void undo(){
        door.down();
    }
}
class GarageDoorCloseCommand implements Command2{
    GarageDoor door;
    public GarageDoorCloseCommand(GarageDoor door){
        this.door = door;
    }
    public void execute(){
        door.down();
    }
    public void undo(){
        door.up();
    }
}
//打开音响同时播放CD命令
class StereoOnWithCDCommand2 implements Command2{
    Stereo2 stereo;
    public StereoOnWithCDCommand2(Stereo2 stereo){
        this.stereo = stereo;
    }
    public void execute(){
        stereo.on();
        stereo.setCD();
        stereo.setVolume();
    }
    public void undo(){
        stereo.off();
    }
}
class StereoCloseWithCDCommand2 implements Command2{
    Stereo2 stereo;
    public StereoCloseWithCDCommand2(Stereo2 stereo){
        this.stereo = stereo;
    }
    public void execute(){
        stereo.off();
    }
    public void undo(){
        stereo.on();
    }
}

4.现在就可以实现遥控器了

//按钮固定功能遥控器
class  ButtonControl{
    Command2[] onCommand2;//给遥控器多个按钮放不同命令,就是一个数组放了好多命令
    Command2[] offCommand2;//一个放开命令,一个放关命令
    Command2 undoCommand;//这个空命令用作撤销
    public ButtonControl(){//构造的时候 给7个插槽分别赋空命令
        onCommand2 = new Command2[7];
        offCommand2 = new Command2[7];
        NoCommand2 noCommand2 = new NoCommand2();
        for(int i=0;i<7;i++){//构造的时候,初始化按钮都放空命令
            onCommand2[i] = noCommand2;
            offCommand2[i] = noCommand2;
        }
        undoCommand =  noCommand2;
    }
    //给每个按钮放固定命令 slot代表位置 第几个按钮放啥命令的
    public void setCommand(int slot,Command2 onCommand,Command2 offCommand){
        onCommand2[slot] = onCommand;
        offCommand2[slot] = offCommand;
    }
    public void onButtonPressed(int slot){//按固定位置的按钮
        onCommand2[slot].execute();//该位置放的按钮对象就去执行它的execute方法
        undoCommand = onCommand2[slot];
    }
    public void offButtonPressed(int slot){//关按钮 同上
        offCommand2[slot].execute();
        undoCommand = offCommand2[slot];
    }
    public void undoButtonPressed(){
        undoCommand.undo();
    }
    public String toString(){
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append("\n-----------------有7个按钮的遥控器------------------\n");
        for(int i=0;i<onCommand2.length;i++){
            stringBuffer.append("[slot"+i+"]"+onCommand2[i].getClass().getName()+" "+offCommand2.getClass().getName()+"\n");
        }
        return stringBuffer.toString();
    }
}

5.现在来简单调试一下

//家电自动化厂商类
public class AutoCompany {
    public static void main(String args[]){
        SimpleControl control = new SimpleControl();
        //打开天花板灯命令
        CeilingLight ceiling = new CeilingLight("嘎嘎");//先new电器
        LightOnCommand2 lightOn = new LightOnCommand2(ceiling);//这个命令操作哪个电器
        control.setCommand(lightOn);//按钮放命令
        control.pressedButton();//按按钮
        //执行打开车库门命令
        GarageDoor door = new GarageDoor();
        GarageDoorOpenCommand doorOpen = new GarageDoorOpenCommand(door);
        control.setCommand(doorOpen);
        control.pressedButton();
        //试试7个按钮的插槽吧
        ButtonControl buttonControl = new ButtonControl();
        CeilingLight ceilingLight = new CeilingLight("天花板灯。。");
        GarageDoor door2 = new GarageDoor();
        Stereo2 stereo = new Stereo2();

        LightOnCommand2 lightOn2 = new LightOnCommand2(ceilingLight);
        LightOffCommand2 lightOff2 = new LightOffCommand2(ceilingLight);
        GarageDoorOpenCommand openDoor = new GarageDoorOpenCommand(door2);
        GarageDoorCloseCommand closeDoor = new GarageDoorCloseCommand(door2);
        StereoOnWithCDCommand2 stereoOn = new StereoOnWithCDCommand2(stereo);
        StereoCloseWithCDCommand2 stereoOff = new StereoCloseWithCDCommand2(stereo);

        buttonControl.setCommand(0, lightOn2, lightOff2);
        buttonControl.setCommand(1, openDoor, closeDoor);
        buttonControl.setCommand(6, stereoOn, stereoOff);

        buttonControl.onButtonPressed(0);
        System.out.println(buttonControl);
        buttonControl.undoButtonPressed();
        buttonControl.onButtonPressed(0);
        buttonControl.offButtonPressed(0);
        buttonControl.offButtonPressed(1);
        buttonControl.onButtonPressed(6);
        buttonControl.offButtonPressed(6);
        buttonControl.undoButtonPressed();
        System.out.println(buttonControl);
        //带状态的吊扇
        CeilingFan2 ceiling2 = new CeilingFan2("吊扇");
        CeilingFanHighCommand hignCommand1 = new CeilingFanHighCommand(ceiling2);
        CeilingFanMediumCommand mediumCommand2 = new CeilingFanMediumCommand(ceiling2);
        buttonControl.setCommand(5, hignCommand1, mediumCommand2);
        buttonControl.onButtonPressed(5);//设置高速
        buttonControl.offButtonPressed(5);//设置中速
        buttonControl.undoButtonPressed();
        System.out.println(buttonControl);
        //宏命令-一次执行所有操作测试  这往下不用看啦
        CeilingLight light = new CeilingLight("天花板灯。。");
        Stereo2 stereo2 = new Stereo2();
        GarageDoor door3 = new GarageDoor();

        LightOnCommand2 lighton = new LightOnCommand2(light);
        LightOffCommand2 lightOff = new LightOffCommand2(light);
        StereoOnWithCDCommand2 stereoOn2 = new StereoOnWithCDCommand2(stereo2);
        StereoCloseWithCDCommand2 stereClose = new StereoCloseWithCDCommand2(stereo2);
        GarageDoorOpenCommand doorOpen2 = new GarageDoorOpenCommand(door3);
        GarageDoorCloseCommand doorClose = new GarageDoorCloseCommand(door3);

        Command2[] commandOns =  {lighton,stereoOn2,doorOpen2};
        Command2[] commandCloses = {lightOff,stereClose,doorClose};

        //MacroCommand macroOn = new MacroCommand(commandOns);
        //MacroCommand macroclose = new MacroCommand(commandCloses);
        //buttonControl.setCommand(3, macroOn, macroclose);

        System.out.println(buttonControl);
        buttonControl.onButtonPressed(3);
        buttonControl.offButtonPressed(3);
    }
}

6.运行结果
已经为您打开天花板的灯。。
正在为你生起车库门。。
已经为您打开天花板的灯。。

—————–有7个按钮的遥控器——————
[slot0]test.LightOnCommand2 [Ltest.Command2;
[slot1]test.GarageDoorOpenCommand [Ltest.Command2;
[slot2]test.NoCommand2 [Ltest.Command2;
[slot3]test.NoCommand2 [Ltest.Command2;
[slot4]test.NoCommand2 [Ltest.Command2;
[slot5]test.NoCommand2 [Ltest.Command2;
[slot6]test.StereoOnWithCDCommand2 [Ltest.Command2;

已经为您关上天花板的灯。。
已经为您打开天花板的灯。。
已经为您关上天花板的灯。。
正在为您关闭车库门。。
已经为您打开音响。。
已经为您放好CD光盘。。
正在为您调节立体声音量。。
已经为您关闭音响。。
已经为您打开音响。。

—————–有7个按钮的遥控器——————
[slot0]test.LightOnCommand2 [Ltest.Command2;
[slot1]test.GarageDoorOpenCommand [Ltest.Command2;
[slot2]test.NoCommand2 [Ltest.Command2;
[slot3]test.NoCommand2 [Ltest.Command2;
[slot4]test.NoCommand2 [Ltest.Command2;
[slot5]test.NoCommand2 [Ltest.Command2;
[slot6]test.StereoOnWithCDCommand2 [Ltest.Command2;

吊扇 速度现在是高速
吊扇 速度现在是中速
吊扇 速度现在是高速

—————–有7个按钮的遥控器——————
[slot0]test.LightOnCommand2 [Ltest.Command2;
[slot1]test.GarageDoorOpenCommand [Ltest.Command2;
[slot2]test.NoCommand2 [Ltest.Command2;
[slot3]test.NoCommand2 [Ltest.Command2;
[slot4]test.NoCommand2 [Ltest.Command2;
[slot5]test.CeilingFanHighCommand [Ltest.Command2;
[slot6]test.StereoOnWithCDCommand2 [Ltest.Command2;

—————–有7个按钮的遥控器——————
[slot0]test.LightOnCommand2 [Ltest.Command2;
[slot1]test.GarageDoorOpenCommand [Ltest.Command2;
[slot2]test.NoCommand2 [Ltest.Command2;
[slot3]test.NoCommand2 [Ltest.Command2;
[slot4]test.NoCommand2 [Ltest.Command2;
[slot5]test.CeilingFanHighCommand [Ltest.Command2;
[slot6]test.StereoOnWithCDCommand2 [Ltest.Command2;

啥也不做命令哦。。
啥也不做命令哦。。


我的理解是这样滴:
这里写图片描述
哎呀妈呀,这图 转不过来了,
意思就是说,遥控器要让灯亮,但是让灯亮这个命令单独拿出来封装了,因为命令有很多,又把命令抽象出一接口command,然后遥控器调接口类型对象的执行方法,具体的子类对象命令去执行它重写的execute方法,这是一个多态的体现,
而具体命令对象又做了什么呢,它在构造的时候,也就是初始化的时候加载了灯类型的对象,在execute里就可以去调灯的具体子类什么灯的重写的开关方法,这也是一处多态的体现,
这样遥控器和灯都是和命令对象打交道,他们互相之间并不熟、不认识,达到了请求者和执行者解耦的效果,
这样你在增加什么电器,或者遥控器有什么改动都不会互相影响,可扩展性强。

猜你喜欢

转载自blog.csdn.net/FightingITPanda/article/details/80807236