前端设计模式(9)--职责链模式

66 阅读3分钟

一, 定义

一系列可能会处理请求的对象被连接成一条链,请求在这些对象之间依次传递,直到可以遇见一个可以处理它的对象. 我们把这些对象称为链中的节点.

image.png

二, 场景和实现

假设我们负责一个售卖手机的电商网站,经过分别交纳 500 元定金和 200 元定金的两轮预定后(订单已在此时生成),现在已经到了正式购买的阶段。

公司针对支付过定金的用户有一定的优惠政策。在正式购买后,已经支付过 500 元定金的用 户会收到 100 元的商城优惠券, 200 元定金的用户可以收到 50 元的优惠券,而之前没有支付定金 的用户只能进入普通购买模式,也就是没有优惠券,且在库存有限的情况下不一定保证能买到。

我们的订单页面是 PHP 吐出的模板,在页面加载之初, PHP 会传递给页面几个字段。

  1. orderType:表示订单类型(定金用户或者普通购买用户), code 的值为 1 的时候是 500 元 定金用户,为 2 的时候是 200 元定金用户,为 3 的时候是普通购买用户。
  2. pay:表示用户是否已经支付定金,值为 true 或者 false, 虽然用户已经下过 500 元定金的 订单,但如果他一直没有支付定金,现在只能降级进入普通购买模式。
  3. stock:表示当前用于普通购买的手机库存数量,已经支付过 500 元或者 200 元定金的用 户不受此限制。

普通的if else 代码在此不再叙述.接下来直接使用职责链模式的代码如下.

//职责链模式

// 业务方法
const order500 = (orderType, pay, stock) => {
  if (orderType === 1 && pay === true) {
    console.log('500元订金预购, 得到100元优惠券!');
  } else {
    return 'next';
  }
};

const order200 = (orderType, pay, stock) => {
  if (orderType === 2 && pay === true) {
    console.log('200元订金预购, 得到50元优惠券!');
  } else {
    return 'next';
  }
};

const orderNormal = (orderType, pay, stock) => {
  if (stock > 0) {
    console.log('普通购买, 无优惠券!');
  } else {
    console.log('手机库存不足!');
  }
};

// 职责链节点
const Chain = function (fn) {
  this.fn = fn;
  this.next = null;
};

// 指定在链中的下一个节点
Chain.prototype.setNext = function (next) {
  return (this.next = next);
};
// 传递请求给某个节点
Chain.prototype.passRequest = function () {
  const ret = this.fn.apply(this, arguments); // 本节点处理请求
  if (ret === 'next') {
    // 本节点无法处理, 就传递请求给下一个节点
    return this.next && this.next.passRequest(arguments);
  }
  return ret; //本节点可以处理, 直接返回结果
};
// 创建职责链节点
const chain500 = new Chain(order500);
const chain200 = new Chain(order200);
const chainNormal = new Chain(orderNormal);
// 设置职责链条
chain500.setNext(chain200).setNext(chainNormal);
// 传递请求到第一个职责链节点,开始处理请求
chain500.passRequest(1, true, 100);

三,总结

职责链模式其实就是通过将原始方法进行了一次包装, 根据本次处理的结果决定是否传递给下一个节点. 降低了请求的发送者和请求的处理者的耦合度.