第七篇 调整类间关系 第二十一章 - 命令模式

  如果说责任链模式关注的是“水平方向”的上下游类间关系,那么命令模式关注的是“垂直方向”的上下级类间关系。
  这里的上下级类间关系是指某功能(或方法)的请求类与执行类之间的调用关系。
  看个例子。

// 设备驱动程序
public class Driver {

  public static void work() {}

}

// 打印服务
public class Printer {

  // 打印
  public void print() {
    // 设备驱动程序执行任务
    Driver.work();
  }

}

  上例中Printer为打印功能的请求类(上级),Driver则为执行类(下级),它们构成了上下级关系。
  看得出来,这是一种紧密的耦合关系,请求类与执行类直接绑定在一起了。如果有扩展需求,我们可以尝试将两者“解耦”。
  来看看命令模式提供的解耦思路。

// 命令接受者
public interface Receiver {

  public void work();

}

// 打印命令接受者
public class PrintReceiver implements Receiver {

  @Override
  public void work() {
    Driver.work();
  }

}

// 命令
public abstract class Command {

  public Receiver receiver;

  // 命令与命令接受者之间的“桥梁”
  public Command(Receiver obj) {
    this.receiver = obj;
  }

  // 执行命令
  public abstract void execute();

}

// 打印命令
public class PrintCommand extends Command {

  public PrintCommand(Receiver obj) {
    super(obj);
  }

  // 执行打印命令
  @Override
  public void execute() {
    super.receiver.work();
  }

}

// 测试类
public class Test {

  public void test() {
    // 命令接受者
    Receiver r = new PrintReceiver();
    // 命令
    Command c = new PrintCommand(r);
    c.execute();
  }

}

  这里设立了“命令”与“命令接受者”两种角色,将直接的功能调用拆分成了需求方“下达命令”与命令接受者“执行命令”两个步骤。
  命令与命令接受者的关联关系建立在桥接模式的基础上,为双方预留了扩展空间。
  这种松散的耦合关系使得我们有机会“拦截”功能调用并植入额外的操作(如维护打印队列)。
  如下所示。

// 打印命令
public class PrintCommand extends Command {

  public PrintCommand(Receiver obj) {
    super(obj);
  }

  // 执行打印命令
  @Override
  public void execute() {
    this.doSomething();// 植入额外的操作
    super.receiver.work();
  }

  private void doSomething() {}

}

  必要时可以引入“通信员”角色,由它专门处理繁重的“拦截命令”工作。
  如下所示。

// 通信员
public class Messenger {

  private Command command;

  public void setCommand(Command obj) {
    this.command = obj;
  }

  public void execute() {
    this.doSomething();// 植入额外的操作
    this.command.execute();
  }

  private void doSomething() {}

}

// 测试类
public class Test {

  public void test() {
    // 命令接受者
    Receiver r = new PrintReceiver();
    // 命令
    Command c = new PrintCommand(r);
    // 通信员传达命令
    Messenger obj = new Messenger();
    obj.setCommand(c);
    obj.execute();
  }

}
posted on 2025-03-28 22:22  星辰河岳  阅读(23)  评论(0)    收藏  举报