Skip to content

命令模式

通过命令模式,我们可以将执行特定任务的对象与调用方法的对象解耦。 假设我们有一个在线食品配送平台。用户可以下单、跟踪和取消订单。

javascript
class OrderManager() {
  constructor() {
    this.orders = []
  }
  // 下单
  placeOrder(order, id) {
    this.orders.push(id)
    return `You have successfully ordered ${order} (${id})`;
  }
  // 跟踪订单
  trackOrder(id) {
    return `Your order ${id} will arrive in 20 minutes.`
  }
  // 取消订单
  cancelOrder(id) {
    this.orders = this.orders.filter(order => order.id !== id)
    return `You have canceled your order ${id}`
  }
}

在 OrderManager 类中,我们可以直接访问 placeOrder 、 trackOrder 和 cancelOrder 方法。

javascript
const manager = new OrderManager();

manager.placeOrder("Pad Thai", "1234");
manager.trackOrder("1234");
manager.cancelOrder("1234");

然而,直接在 manager 实例上调用方法存在一些缺点。我们可能会在后期决定重命名某些方法,或者方法的功能会发生变化。

假设我们将 placeOrder 重命名为 addOrder !这意味着我们必须确保在代码库的任何地方都不调用 placeOrder 方法,这在大型应用程序中可能会非常棘手。相反,我们希望将方法与 manager 对象解耦,并为每个命令创建单独的命令函数!

所有让我们重构 OrderManager 类:它将不再包含 placeOrder 、 cancelOrder 和 trackOrder 方法,而将只有一个方法: execute 。这个方法将执行它所接收到的任何命令。

每个命令都应该能够访问管理器的 orders ,我们将它作为其第一个参数传递。

javascript

class OrderManager {
  constructor() {
    this.orders = [];
  }

  execute(command, ...args) {
    return command.execute(this.orders, ...args);
  }
}

然后我们需要为订单管理器创建三个 Command

  • PlaceOrderCommand
  • CancelOrderCommand
  • TrackOrderCommand
javascript
// 命令基类
class Command {
  constructor(execute) {
    this.execute = execute;
  }
}
// 下单命令
function PlaceOrderCommand(order, id) {
  return new Command((orders) => {
    orders.push(id);
    return `You have successfully ordered ${order} (${id})`;
  });
}
// 取消订单命令
function CancelOrderCommand(id) {
  return new Command((orders) => {
    orders = orders.filter((order) => order.id !== id);
    return `You have canceled your order ${id}`;
  });
}
// 跟踪订单命令
function TrackOrderCommand(id) {
  return new Command(() => `Your order ${id} will arrive in 20 minutes.`);
}

Released under the MIT License.