javascript技巧

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript技巧 > JS命令模式

JS设计模式之命令模式的用法详解

作者:慕仲卿

JavaScript中的命令模式是一种设计模式,它提供了一种将命令封装为对象的方式,从而允许我们将请求与实际执行该请求的操作对象解耦,这种模式可以在不同的场景中使用,例如实现撤销/重做操作、队列任务等,本文我们将讲解命令设计模式在JS中的使用

相关定义:

自我理解:

解耦体现:

代码举例1:

// 接收者对象
class Light {
    turnOn() {}
    turnOff() {}
}
// 命令接口
abstract class Command {
    abstract execute():void;
}
// 具体命令:打开灯
class TurnOnCommand extends Command {
    constructor(public light: Light) { super() }
    execute() { this.light.turnOn() }
}
// 具体命令:关闭灯
class TurnOffCommand extends Command {
    constructor(public light: Light) { super() }
    execute() { this.light.turnOff() }
}
// 调用者对象
class RemoteControl {
    command: Command;
    setCommand(command: Command) { this.command = command }
    pressButton() { this.command.execute() }
}
// 使用示例
// 创建执行者
const light = new Light();
// 创建具体命令对象,封装执行者
const turnOnCommand = new TurnOnCommand(light);
const turnOffCommand = new TurnOffCommand(light);
// 创建调用者对象
const remoteControl = new RemoteControl();
// 设置具体命令对象然后执行
remoteControl.setCommand(turnOnCommand);
remoteControl.pressButton();

代码举例2:

使用命令设计模式可以灵活组合网络请求,如下所示:

// 请求接收者
class Reciever {
  async get(path: string) {
    const res = await fetch(`https://rec.example.com/${path}`);
    const data = await res.json();
  }
}
// 命令接口
class Cmd { exe() {} }
// 具体命令:发送请求
class RCd extends Cmd {
  constructor(public rec, public url) {
    super();
  }
  exe() {
    return this.rec.get(this.url);
  }
}
// 调用者对象
class RM {
  cQueue: Cmd[] = [];
  add(command: Cmd) {
    this.cQueue.push(command);
  }
  pReq() {
    const promises = this.cQueue.map((command) => command.exe());
    return Promise.all(promises);
  }
}
// 使用示例
const rec = new Reciever(); // 创建请求接收者
const rM = new RM(); // 创建请求管理者
// 添加具体请求命令
rM.add(new RCd(rec, 'data1'));
rM.add(new RCd(rec, 'data2'));
rM.add(new RCd(rec, 'data3'));
rM.pReq()
  .then(() => {
    console.log('所有请求已完成');
  })
  .catch((error) => {
    console.error('请求出错:', error);
  });

代码举例3:

使用命令设计模式实现撤销和重做,用到了栈数据结构,如下所示:

// 命令接口:想要用命令策略实现撤销、重做就必须先在抽象接口中定义好撤销的接口
abstract class Cmd {
  abstract exe(): void;
  abstract undo(): void;
}
// 具体命令类 - 加法命令
class AddCmd extends Cmd {
  constructor(public rec: Rec, public value: number) {
    super();
  }
  exe() {
    this.rec.add(this.value);
  }
  undo() {
    this.rec.subtract(this.value);
  }
}
// 接收者类
class Rec {
  result = 0;
  add(value: number) { this.result += value }
  subtract(value: number) { this.result -= value }
}
// 调用者/发送者
class Invoker {
  cmds: Cmd[] = [];
  xcmd: Cmd[] = [];
  exe(cmd: Cmd) {
    cmd.exe();
    this.cmds.push(cmd);
  }
  // 重点
  undo() {
    const cmd = this.cmds.pop();
    if (!cmd) return;
    cmd.undo();
    this.xcmd.push(cmd);
  }
  // 重点
  redo() {
    const cmd = this.xcmd.pop();
    if (cmd) {
      cmd.exe();
      this.cmds.push(cmd);
    }
  }
}
// 示例用法
const rec = new Rec(); // 创建接收者对象
const ivk = new Invoker(); // 创建调用者对象
const addCmd = new AddCmd(rec, 5); // 创建加法命令
ivk.exe(addCmd); // 执行加法命令,结果为:5
ivk.undo(); // rec.result = 0
ivk.redo(); // rec.result = 5

命令设计模式和策略设计模式的不同:

原生使用

下面这些是 JavaScript 中常见的原生部分,它们在某种程度上使用到了命令模式的思想和机制。通过封装行为成具体的对象并在需要时进行调用,这些原生功能可以提供更灵活、可扩展的方式来处理相关的请求或操作。

业务实践:

也就是说但凡见到按钮,都可以使用命令设计模式。

以上就是JS设计模式之命令模式的用法详解的详细内容,更多关于JS命令模式的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文