设计模式随笔-命令模式

命令模式

封装调用方法,命令模式能够把方法调用封装到一个起来。这样,命令方法就不用在乎方法内部是做什么的了,只需要关心封装的过程,是开还是关闭某些东西。
它能做记录日志,或者撤销等。

家电自动化遥控器(命令模式详解)

现在我们有一个需求,就是帮家电厂商设计一个遥控器,这个遥控器有4个链接设备的开关,和一个撤销按钮。如下图所示:
遥控器
现在我们看看厂商的家电类有什么特征:
厂商家电类简图

第一个命令对象

首先我们要创建一个命令接口,是接口模式的基础:

public interface Command {
    void execute();
}

所有命令对象都要包含实现execute这个方法,下面我们来实现一个Light()对象的开,命令对象吧。

public class LightOnCommand implements Command {
    private Light light;

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

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

这是一个Light对象的(开)命令对象。完成了第一个命令对象之后,我们来看看怎么使用该命令对象吧。假设我们有一个简单的遥控控制器,它只对应一个按钮和一个插槽。

public class SimpleRemoteControl {
    private Command command;

    public SimpleRemoteControl() {
    }

    public void setCommand(Command command) {
        this.command = command;
    }
    //按下按钮的动作
    public void buttonWasPressed(){
        command.execute();
    }
}

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

命令模式的基础模型:
命令模式的基础模型
undo()方法在下面设计更复杂的命令模式的时候会讲到。

复杂的命令模式

下面是能够控制7个家电设备和一个撤回按钮的遥控器的代码:

public class RemoteControl {
    Command[] onCommands;  //开命令
    Command[] offCommands;  //关命令
    Command undoCommand;  //撤回命令

    public RemoteControl() {
        onCommands = new Command[7];
        offCommands = new Command[7];
        Command command = new NoCommand();  //初始化为什么都不做的命令对象
        for (int i=0; i<7; i++){
            onCommands[i] = command;
            offCommands[i] = command;
        }
        undoCommand = command;
    }

    public void setCommand(int slot, Command onCommand, Command offCommand){
        onCommands[slot] = onCommand;
        offCommands[slot] = offCommand;
    }

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

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

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("------test------");
        for (int i=0; i<onCommands.length; i++){
            sb.append("slot "+i+" "+onCommands[i].getClass().getName())
                    .append(" "+offCommands[i].getClass().getName());
        }
        return sb.toString();
    }
}

下面是点灯开的命令:

public class LightOnCommand implements Command {
    private Light light;

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

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

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

点灯关的命令:

public class LightOffCommand implements Command {
    private Light light;

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

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

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

继承Common的命令:

public interface Command {
    //执行
    void execute();
    //撤回
    void undo();
}

undo就是命令的撤销方法,就像点灯的开命令,那么他的撤销功能当然是点灯的关啦。
灯对象:

public class Light {
    private boolean flag;  //点灯开关的标志位

    public void on(){
        System.out.println("light is on");
    }

    public void off(){
        System.out.println("light is off");
    }
}

测试方法:

public void test2(){
        RemoteControl remoteControl = new RemoteControl();
        Light light = new Light();
        LightOnCommand lightOnCommand = new LightOnCommand(light);
        LightOffCommand lightOffCommand = new LightOffCommand(light);
        for (int i=0; i<5; i++){
            //这里假设插槽控制了5个灯泡(为了方便,实际可以创建多几个家电类和命令),剩下两个没有插电器
            remoteControl.setCommand(i, lightOnCommand, lightOffCommand);
        }
        System.out.println(remoteControl);
        remoteControl.onButtonWasPushed(1);
        remoteControl.offButtonWasPushed(1);
    }

命令模式的更多用途

命令可以将运算块打包,然后将它传来传去,就像是一般的对象一样。现在,即使在命令对象被调用之后,运算依然可以被调用

工作队列

假设当前有一个命令队列,从一端添加需要完成的工作命令,在另一端是一个线程,负责取出线程,执行execute()方法。

总结

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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值