命令模式 :封装调用

定义

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

命令模式设计图
在这里插入图片描述

模式的意义

命令模式,主要的是将请求对象和执行对象进行解耦,也就是类图里面的Invoker和Receiver,这个模式主切入的点很小,但是应用很广,也是解耦思想一个比较重要的模式。

// 命令接口
public interface Command {  
    void execute(); 
    void undo();
}
// 开灯功能
public class LightOnCommand implements Command {

    private Light light;
    
    public LightOnCommand(Light light) {
        this.light = light;
    }
    public void execute() {
        light.on();
    }
    public void undo() {
        light.off();
    }
// 关灯命令   
public class LightOffCommand implements Command {

    private Light light;

    public LightOffCommand(Light light) {
        this.light = light;
    }
    public void execute() {
        light.off();
    }
    public void undo() {
        light.on();
    }
}

public class RemoteInvoker {

    /**
     * 开关命令数组,模拟有很多对开关数组
     */
    private Command[] onCommands;
    private Command[] offCommands;
  
    private Command undoCommand;

    public RemoteInvoker(int length) {
        // 有几组开关,就设置多少数组
        onCommands = new Command[length];
        offCommands = new Command[length];
        // 把每个命令初始化成空命令,避免空指针异常
        Command noCommand = new NoCommand();
        undoCommand = noCommand;
        for (int i = 0; i < length; i++) {
            onCommands[i] = noCommand;
            offCommands[i] = noCommand;
        }
    }

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


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

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

    public void undoButton() {
        undoCommand.undo();
    }
}

客户端

public class RemoteClient {

    public static void main(String[] args) {
        // 1、创建接收者
        Light light = new Light();
        // 2、创建命令对象
        LightOnCommand lightOnCommand = new LightOnCommand(light);
        LightOffCommand lightOffCommand = new LightOffCommand(light);
        // 3、创建一组开关并用命令对象装载它
        RemoteInvoker invoker = new RemoteInvoker(1);
        invoker.setCommond(0, lightOnCommand, lightOffCommand);
        // 4、测试
        invoker.onButton(0);
        invoker.offButton(0);
        invoker.undoButton();
    }
}

队列

命令可以将运算打包,放入一个我们设置的工作队列里面,一端负责添加命令,然后另一端则是线程,线程从队列中取出一个命令,调用他的execute()方法,等待这个调用完成,然后将此命令对象丢弃,再取出下一个命令。我们之前用Redis设计抢红包的时候,就是将用户抢到的红包对象放到队列里面,然后由线程循环的将这个对象消耗掉,虽然没有利用命令继承,但也是这种概念的简化版。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章