设计模式学习笔记(六)——命令模式

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

UML类图
在这里插入图片描述

Command:为所有的命令声明了一个接口,调用命令对象的execute方法即可让接收者进行相关动作。
ConcreteCommand:定义了动作和接收者之间的绑定关系,调用者只需要调用其execute方法即可发出请求,然后由ConcreteCommand调用接收者的动作。
Receiver:接受者知道如何进行必要的工作,实现这个请求,任何类都可作为接收者。
Invoker:调用者持有一个Command引用,调用其execute方法发出请求。

分析: 命令对象将动作和接收者包进对象中,只暴露出一个execute方法,当该方法被调用时,接收者就会进行这些动作,从外面看,其他对象并不知道究竟哪个接收者进行了哪些动作。

示例
有一个具有7个插槽的遥控器,每个插槽可以制定到不同的家电上,都有开和关按钮,还有一个整体的撤销功能。

接收者

public class Door {

    private String name;

    public Door(String name) {
        this.name = name;
    }

    public void on(){
        System.out.println(name+":打开门");
    }

    public void off(){
        System.out.println(name+":关上门");
    }
}

public class Light {

    private String name;

    public Light(String name) {
        this.name = name;
    }

    public void on(){
        System.out.println(name+":灯开了");
    }

    public void off(){
        System.out.println(name+":灯关了");
    }

}

public class Stereo  {

    private String name;

    public Stereo(String name) {
        this.name = name;
    }

    public void off(){
        System.out.println(name+":CD机关闭");
    }

    public void on(){
        System.out.println(name+":CD机打开");
    }

    public void setCD(){
        System.out.println("CD已插入");
    }

    public void setVolumn(int volumn){
        System.out.println("设置音量为:"+volumn);
    }
}

命令接口

public interface Command {
    void execute();
}

具体命令类

public class GarageDoorCloseCommand implements Command {

    private Door door;

    public GarageDoorCloseCommand(Door door) {
        this.door = door;
    }


    @Override
    public void execute() {
        door.off();
    }
}
public class GarageDoorOpenCommand implements Command {

    private Door door;

    public GarageDoorOpenCommand(Door door) {
        this.door = door;
    }

    @Override
    public void execute() {
        door.on();
    }
}
public class LightOffCommand implements Command {

    private Light light;

    public LightOffCommand(Light light) {

        this.light = light;
    }

    @Override
    public void execute() {
        light.off();
    }
}
public class LightOnCommand implements Command {

    private Light light;

    public LightOnCommand(Light light) {
        this.light = light;
    }

    @Override
    public void execute() {
        light.on();
    }
}
public class NoCommand implements Command {
    @Override
    public void execute() {
        System.out.println("初始化");
    }
}
public class StereoOffCommand implements Command {

    private Stereo stereo;

    public StereoOffCommand(Stereo stereo) {
        this.stereo = stereo;
    }

    @Override
    public void execute() {
        stereo.off();
    }
}
public class StereoOnCommand implements Command {

    private Stereo stereo;

    public StereoOnCommand(Stereo stereo) {
        this.stereo = stereo;
    }

    @Override
    public void execute() {
        stereo.on();
        stereo.setCD();
        stereo.setVolumn(11);
    }
}

调用者

public class RemoteControl {

    private Command[] onCommands;
    private Command[] offCommands;

    public RemoteControl() {
        onCommands = new Command[7];
        offCommands = new Command[7];

        NoCommand 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){
        onCommands[slot] = onCommand;
        offCommands[slot] = offCommand;
    }

    public void onButtonWasPushed(int slot){
        onCommands[slot].execute();
    }

    public void offButtonWasPushed(int slot){
        offCommands[slot].execute();
    }

    @Override
    public String toString() {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("\n---------遥控器----------\n");
        for(int i = 0;i < onCommands.length;i++){
            stringBuilder.append("[卡槽"+i+"]"+onCommands[i].getClass().getName()+"  "+"[卡槽"+i+"]"+offCommands[i].getClass().getName()+"\n");
        }
        return stringBuilder.toString();
    }
}

测试

public class RemoteLoader {

    public static void main(String[] args) {
        RemoteControl remoteControl = new RemoteControl();
        Light livingLight = new Light("卧室灯");
        Light kitchenLight = new Light("厨房灯");
        Door garageDoor = new Door("车库门");
        Stereo stereo = new Stereo("欣欣");

        LightOnCommand livingLightOnCommand = new LightOnCommand(livingLight);
        LightOnCommand kitchenLightOnCommand = new LightOnCommand(kitchenLight);
        LightOffCommand livingLightOffCommand = new LightOffCommand(livingLight);
        LightOffCommand kitchenLightOffCommand = new LightOffCommand(kitchenLight);

        GarageDoorOpenCommand garageDoorOpenCommand = new GarageDoorOpenCommand(garageDoor);
        GarageDoorCloseCommand garageDoorCloseCommand = new GarageDoorCloseCommand(garageDoor);

        StereoOnCommand stereoOnCommand = new StereoOnCommand(stereo);
        StereoOffCommand stereoOffCommand = new StereoOffCommand(stereo);

        remoteControl.setCommand(0,livingLightOnCommand,livingLightOffCommand);
        remoteControl.setCommand(1,kitchenLightOnCommand,kitchenLightOffCommand);
        remoteControl.setCommand(2,garageDoorOpenCommand,garageDoorCloseCommand);
        remoteControl.setCommand(3,stereoOnCommand,stereoOffCommand);

        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);

    }
}

在这里插入图片描述

更多用途
1、队列请求:实现命令接口的对象被放入队列中,线程从队列中提取命令对象,并将其从队列中删除,调用其execute方法,完成动作,再去处理下一个命令对象。工作队列对象并不在乎到底做些什么工作,它们只是取出命令对象,调用execute方法。
2、日志请求:通过在命令对象中添加store和load两个方法,每调用一次execute,命令对象被store到磁盘上,如果系统出状况,我们从本地中调用load方法,按次序批量执行命令对象的execute方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值