かかってこいよ NakamuraEmi
  1. 1 かかってこいよ NakamuraEmi
  2. 2 Last Surprise Lyn
  3. 3 Libertus Chen-U
  4. 4 One Last You Jen Bird
  5. 5 Time Bomb Veela
  6. 6 Warcry mpi
  7. 7 BREAK IN TO BREAK OUT Lyn
  8. 8 Life Will Change Lyn
  9. 9 Flower Of Life 发热巫女
  10. 10 Hypocrite Nush
2017-07-16 12:19:50

设计模式——职责链模式

职责链模式将多个有机会处理请求的对象串联起来,将请求者和接受者解耦并将请求从链的入口传入,直到有一个对象能处理它为止。


实例演示

假设现在有个卖手机的活动,用户来源有3类:

  1. 预付500定金的可以享受100元优惠。
  2. 预付200定金的可以享受50元优惠。
  3. 没有预付不享受优惠。

接收到的参数有订单类型orderType,定金pay,库存stock。我们先用简单的逻辑来实现这个业务功能:

let order = function(orderType, pay, stock) {
  if (orderType === 1) {
    if (pay === true) {
      console.log('得到100元优惠');
    } else {
      if (stock > 0) {
        console.log('无优惠');
      } else {
        console.log('手机无库存');
      }
    }
  }
  else if (orderType === 2) {
    if (pay === true) {
      console.log('得到50元优惠');
    } else {
      if (stock > 0) {
        console.log('无优惠');
      } else {
        console.log('手机无库存');
      }
    }
  }
  else if (orderType === 3) {
    if (stock > 0) {
      console.log('无优惠');
    } else {
      console.log('手机无库存');
    }
  }
}

职责链模式重构

虽然业务是实现了,但所有的逻辑都耦合在了一起,基本上没有可拓展性。下面用职责链模式重构一下,将3种情况拆分为3个接收节点。

let order500 = function(orderType, pay, stock) {
  if (orderType === 1 && pay === true) {
    console.log('得到100元优惠');
  } else {
    order200(orderType, pay, stock); // 传递请求到下一节点
  }
};
let order200 = function(orderType, pay, stock) {
  if (orderType === 2 && pay === true) {
    console.log('得到50元优惠');
  } else {
    orderNormal(orderType, pay, stock); // 传递请求到下一节点 
  }
};
let orderNormal = function(orderType, pay, stock) {
  if (stock > 0) {
    console.log('无优惠');
  } else {
    console.log('手机无库存');
  }
};

可以看到我们成功将不同的节点拆分开来。虽然有了进步,但传递的方式还是耦合在了业务中。如果以后要更改传递方法,就必须深入业务内部去修改。我们可以进一步优化。首先我们约定如果某个节点不能处理请求则返回一个标记字符串next表示需要传递请求。

let order500 = function(orderType, pay, stock) {
  if (orderType === 1 && pay === true) {
    console.log('得到100元优惠');
  } else {
    return 'next';
  }
};
let order200 = function(orderType, pay, stock) {
  if (orderType === 2 && pay === true) {
    console.log('得到50元优惠');
  } else {
    return 'next';
  }
};
let orderNormal = function(orderType, pay, stock) {
  if (stock > 0) {
    console.log('无优惠');
  } else {
    console.log('无库存');
  }
};

接下来我们就这些节点处理函数包装成职责链节点,每个节点应该有下一个节点的数据和传递请求的方法。通过定义构造函数 Chain来进行包装。

let Chain = function(fn) {
  this.fn = fn;
  this.successor = null; // 保存下一个节点
};
Chain.prototype.setNextSuccessor = function(successor) { // 设置下一节点对象
  return this.successor = successor;
};
Chain.prototype.passRequest = function() { // 接受请求,无法处理则传递
  let ret = this.fn.apply(this, arguments); 
  if (ret === 'next') {
    return this.successor && this.successor.passRequest.apply(this.successor, arguments);
  }
  return ret;
};

这样我们就完全解耦了请求者和接受者之间的关系。不需要知道哪个接受者可以处理请求,只要将请求传给这条职责链就可以。


小结

职责链模式虽然降低了耦合性,但使得程序中多了一些节点对象,可能对于大多数请求来说,大部分节点没有起到作用。如果从优化性能的方面考虑,也要注意到请求被不同节点处理的频率并进一步针对处理,以免过长职责链带来性能损耗。

-- EOF --

添加在分类「 前端开发 」下,并被添加 「设计模式」 标签。

文章目录

 - [实例演示](#实例演示)
   - [职责链模式重构](#职责链模式重构)
 - [小结](#小结)
回到首页