设计模式之命令模式

命令模式

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

今天我们讲解命令模式的模型就是遥控器,将遥控器的每个插槽,对应到一个命令这样就能让遥控器变成“调用者”。当按下按钮,相应命令对象的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.NoCommand

Living 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.NoCommand

Living Room light  off 
命令模式的应用场景:当需要将发出请求的对象和执行请求的对象解耦的时候,使用命令模式。
宏命令是命令的一种简单的延伸,允许调用多个命令。宏方法也可以支持撤销,这里我就不介绍宏命令,有兴趣的话大家可以查一下命令模式中的宏命令。
下回我们来一起学习适配器模式。

命令模式是一种行为型设计模式,它将请求封装成一个对象,从而使得请求的发送者和接收者解耦。在命令模式中,请求以命令的形式包裹在对象中,并传递给调用对象。调用对象寻找可以处理该命令的合适的对象,并将命令传递给相应的对象,该对象执行命令。 在C语言中,可以使用函数指针来实现命令模式。具体步骤如下: 1. 定义一个命令接口,该接口包含一个执行命令的方法。 2. 创建具体的命令类,实现命令接口,并在执行方法中调用相应的函数。 3. 创建一个调用者类,该类包含一个命令对象,并提供一个执行命令的方法。 4. 在调用者类中,将命令对象传递给相应的对象,并调用命令对象的执行方法。 下面是一个简单的示例代码: ```c #include <stdio.h> // 定义命令接口 typedef struct { void (*execute)(void); } Command; // 创建具体的命令类 typedef struct { Command command; void (*function)(void); } ConcreteCommand; void concreteCommand_execute(void) { printf("执行具体的命令\n"); } // 创建调用者类 typedef struct { Command *command; void (*setCommand)(Command *command); void (*executeCommand)(void); } Invoker; void invoker_setCommand(Command *command) { Invoker *invoker = (Invoker *)command; invoker->command = command;} void invoker_executeCommand(void) { Invoker *invoker = (Invoker *)invoker->command; invoker->command->execute(); } int main() { // 创建具体的命令对象 ConcreteCommand concreteCommand; concreteCommand.command.execute = concreteCommand_execute; concreteCommand.function = concreteCommand_execute; // 创建调用者对象 Invoker invoker; invoker.setCommand((Command *)&concreteCommand); invoker.executeCommand(); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值