设计模式之命令模式

95 阅读2分钟

一、基本概念

  • 命令模式(Command Pattern):我们经常需要向某些对象发送请求,但时并不知道请求的接收者是谁,也不知道被请求的操作是哪一个。我们只需要在程序运行时指定具体的请求接收者即可,此时,可以用命令模式来设计。
  • 命令模式使得请求发送者和请求接收者消除彼此之间的耦合,让对象之间的调用关系更加灵活,实现解耦。
  • 在命令模式中,会将一个请求封装成一个对象,以便使用不同参数来表示不同的请求(即命名),同时命令模式也支持可撤回操作。
  • 命令模式的角色及职责
    • Invoker:调用者角色
    • Command:命令角色,需要执行的所有命令都在这里,可以是接口或抽象类
    • Receiver:接收者角色,知道如何实施和执行一个请求相关的操作
    • ConcreteCommand:将一个接受者对象与一个动作绑定,调用接受者相应的操作,实现execute

二、智能生活项目

在这里插入图片描述

public interface Command {
  /**
   * 执行命令
   */
  void execute();

  /**
   * 撤回命令
   */
  void undo();
}
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();
  }
}
public class NoCommand implements Command {
  @Override
  public void execute() {
  }
  @Override
  public void undo() {
  }
}
public class Light {
  public void on() {
    System.out.println("开灯");
  }

  public void off() {
    System.out.println("关灯");
  }
}
public class RemoteController {
  Command[] onCommands;
  Command[] offCommands;
  Command undoCommand;

  public RemoteController(int size) {
    onCommands = new Command[size];
    offCommands = new Command[size];

    for (int i = 0; i < size; i++) {
      onCommands[i] = new NoCommand();
      offCommands[i] = new NoCommand();
    }
  }

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

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

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

  public void undoButtonWadPushed() {
    undoCommand.undo();
  }
}
public class Client {
  public static void main(String[] args) {
    Light light = new Light();
    LightOnCommand lightOnCommand = new LightOnCommand(light);
    LightOffCommand lightOffCommand = new LightOffCommand(light);
    RemoteController remoteController = new RemoteController(3);
    remoteController.setCommand(0, lightOnCommand, lightOffCommand);
    remoteController.onButtonWasPushed(0);
    remoteController.offButtonWasPushed(0);
    remoteController.undoButtonWadPushed();
  }
}

三、总结

  • 容易设计一个命令队列,只要把命令对象放到队列,就可以多线程执行命令
  • 容易实现对请求的撤销和重做
  • 空命令也是一种设计模式,它为我们省去了判空的操作。
  • 命令模式经典的应用场景:界面的一个按钮都是一条命令、模拟cmd命令的订单的撤回、恢复、触发-反馈机制