设计模式之命令模式

命令模式

什么是命令模式

命令模式是将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或记录请求日志,以及支持可撤销的操作。

原理图

在这里插入图片描述

为什么要用命令模式

还记得在外观模式中我们所提到的智慧生活吗?

我们来仔细想一下这个逻辑,智慧助手相当于一个遥控器,用于发出命令,让接收端(具体智能家居)做出相应的反应。

在我们当时的实现中,只是体现出了智慧助手的统一调用,但并没有体现出“命令”,现在,让我们来体现一下“命令”。

假设现在只有灯和空调两个智能家居:

public class Lamp {
    public void turnOn() {
        System.out.println("开灯");
    }

    public void turnOff() {
        System.out.println("关灯");
    }
}
public class AirConditioner {
    public void turnOn() {
        System.out.println("开空调");
    }

    public void turnOff() {
        System.out.println("关空调");
    }
}

要有一个命令接口:

public interface ICommand {
    void execute(); //执行

    void undo();//撤销
}

对应操作有对应具体命令:

public class LampOnCommand implements ICommand {
    private Lamp lamp;

    public LampOnCommand(Lamp lamp) { //给命令设置一个接收器。
        this.lamp = lamp;
    }

    @Override
    public void execute() { //执行操作
        lamp.turnOn();
    }

    @Override
    public void undo() { //后悔,不做
        lamp.turnOff();
    }
}
public class LampOffCommand implements ICommand {
    private Lamp lamp;

    public LampOffCommand(Lamp lamp) {
        this.lamp = lamp;
    }

    @Override
    public void execute() {
        lamp.turnOff();
    }

    @Override
    public void undo() {
        lamp.turnOn();
    }
}
public class AirConditionerOnCommand implements ICommand {
    private AirConditioner airConditioner;

    public AirConditionerOnCommand(AirConditioner airConditioner) {
        this.airConditioner = airConditioner;
    }

    @Override
    public void execute() {
        airConditioner.turnOn();
    }

    @Override
    public void undo() {
        airConditioner.turnOff();
    }
}
public class AirConditionerOffCommand implements ICommand {
    private AirConditioner airConditioner;

    public AirConditionerOffCommand(AirConditioner airConditioner) {
        this.airConditioner = airConditioner;
    }

    @Override
    public void execute() {
        airConditioner.turnOff();
    }

    @Override
    public void undo() {
        airConditioner.turnOn();
    }
}

为了避免判空,做一个空命令:

//在调用时,存储的undoCommand默认是空命令,即使调用也无事发生,避免了对空引用的判断
public class NullCommand implements ICommand {
    @Override
    public void execute() {}

    @Override
    public void undo() {}
}

智慧助手:

public class SmartAssistant {
    private List<ICommand> turnOnCommands; //存储开命令
    private List<ICommand> turnOffCommands; //存储关命令
    private ICommand undoCommand = new NullCommand(); //存储上一条命令,默认为空

    public SmartAssistant() {
        this.turnOnCommands = new ArrayList<>();
        this.turnOffCommands = new ArrayList<>();
    }

    public void setCommand(int number, ICommand turnOnCommand, ICommand turnOffCommand) {
        if (number >= turnOnCommands.size()){//防止越界
            turnOffCommands.add(turnOffCommand);
            turnOnCommands.add(turnOnCommand);
            number = turnOffCommands.size()-1;
        }
        else{
            turnOnCommands.set(number, turnOnCommand);
            turnOffCommands.set(number,turnOffCommand);
        }

        System.out.println("对"+number+"号按键设置命令");
    }

    public void clickOnButton(int number){ //点击开按钮
        turnOnCommands.get(number).execute();
        undoCommand = turnOnCommands.get(number);
    }

    public void clickOffButton(int number){//点击关按钮
        turnOffCommands.get(number).execute();
        undoCommand = turnOffCommands.get(number);
    }

    public void undo(){//撤销,这里可以做一个栈用于维护undo命令,为简化演示未做实现。
        undoCommand.undo();
        undoCommand = new NullCommand();
    }
}

进行调用:

public class Person {
    public static void main(String[] args) {
        Lamp lamp = new Lamp();
        AirConditioner airConditioner = new AirConditioner();
        SmartAssistant smartAssistant = new SmartAssistant();

        //设置按键(连接智慧家居)
        smartAssistant.setCommand(0,new LampOnCommand(lamp),new LampOffCommand(lamp));
        smartAssistant.setCommand(1,new AirConditionerOnCommand(airConditioner),new AirConditionerOffCommand(airConditioner));
        //点击
        smartAssistant.clickOnButton(0);
        smartAssistant.clickOffButton(0);

        smartAssistant.clickOnButton(1);
        smartAssistant.clickOffButton(1);
        //撤销
        smartAssistant.undo();
    }
}

运行结果:

对0号按键设置命令
对1号按键设置命令
开灯
关灯
开空调
关空调
开空调

这样,我们通过一个ICommand的接口,实现的命令的传输,同时有了后悔的选择。

相比于在外观模式中的实现方式而言,更符合现实,智慧助手是通过发命令,而非直接找到家居做操作的方式实现智慧生活。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值