设计模式系列-命令模式-Command

案例

我们需要开发一个遥控器,遥控器上的按钮可以开关电灯和空调,这个需求通常的实现如下伪代码:

if(buttonPressed == button1){
	lights.on()
}else if(buttonPressed == button2){
	airConditioner.on()
}

遥控器类 RemoteControl 耦合每个按钮关联的业务实现,比如上面的例子耦合了 light 和 airConditioner,如果业务有新需求需支持电视的控制,类 RemoteControl 的复杂度和耦合度逐步增加,那如何化解复杂度和解耦类 RemoteControl 呢?此时可以用命令模式来解决。

命令模式

官方定义:将一个请求封装成一个对象,然后你可以用不同的请求去参数化其他的对象,还可以排队或者记录请求,以及支持可撤销的操作。

官方定义比较抽象,难以理解,后面我们重构上面的例子,同时解释这个定义。

命令模式的主要概念

  • Command
    声明执行操作的接口
  • ConcreteCommand
    命令接口的实现类,会引用另外一个类来执行具体的业务逻辑,这个类称为接收者
  • Client
    创建一个具体命令对象并设定它的接收者
  • Invoker
    调用命令执行请求
  • Receiver
    命令的具体业务的服务提供者,任何类都可以当接收者

具体实现

首先定义接口和类,如下:
接口 Command 和开关灯命令实现类 LightOnCommandLightOffCommand 以及空调开关命令实现类 AirConditionerOnCommand , AirConditionerOffCommand,这些类的对象就是定义提到的封装请求的对象。
接收者类 LightAirConditioner
遥控器类 RemoteControl

public interface Command {

    void execute();

}

public class Light {

    public void on(){
        System.out.println("开灯");
    }

    public void off(){
        System.out.println("关灯");
    }
}

public class LightOnCommand implements Command{

    private final Light light;

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

    @Override
    public void execute() {
        light.on();
    }
}

public class LightOffCommand implements Command{

    private final Light light;

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

    @Override
    public void execute() {
        this.light.off();
    }
}

public class AirConditioner {

    public void on(){
        System.out.println("开空调");
    }

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

public class AirConditionerOnCommand implements Command{

    private final AirConditioner airConditioner;

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

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

public class AirConditionerOffCommand implements Command {

    private final AirConditioner airConditioner;

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

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

public class RemoteControl {

    private Command btn;

    public void setBtn(Command btn) {
        this.btn = btn;
    }

    public void buttonWasPressed(){
        btn.execute();
    }
}

public class RemoteControlTest {

    public static void main(String[] args) {
        RemoteControl remoteControl = new RemoteControl();
        Light light = new Light();
        AirConditioner airConditioner = new AirConditioner();
        remoteControl.setBtn(new LightOnCommand(light));
        remoteControl.buttonWasPressed();
        remoteControl.setBtn(new LightOffCommand(light));
        remoteControl.buttonWasPressed();
        remoteControl.setBtn(new AirConditionerOnCommand(airConditioner));
        remoteControl.buttonWasPressed();
        remoteControl.setBtn(new AirConditionerOffCommand(airConditioner));
        remoteControl.buttonWasPressed();
    }
}

运行日志:

开灯
关灯
开空调
关空调

总结

从上面实现中可以看到,用接口 Command 解耦了遥控器和具体动作执行者,遥控器上的按钮不必关心具体动作执行者,而且按钮可以动态更换命令对象来操作不同设备,从这点也解释定义提到的,用封装的对象来参数化其他的对象,这里的遥控器的按钮就是被Command 参数化了, 将来新增设备时只需新增Command的实现类,符合开闭原则
此实现还有一个优点,简化了 RemoteControl 的实现,此类不在依赖或导入类 Light, AirConditoner

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值