资讯专栏INFORMATION COLUMN

JS每日一题:设计模式-如何理解职责链模式?

lifesimple / 1401人阅读

摘要:提交请求的对象并不明确知道哪一个对象将会处理它也就是该请求有一个隐式的接受者。

20190412期

设计模式-如何理解职责链模式?

定义: 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止

也就是说,请求以后,从第一个对象开始,链中收到请求的对象要么亲自处理它,要么转发给链中的下一个候选者。提交请求的对象并不明确知道哪一个对象将会处理它——也就是该请求有一个隐式的接受者(implicit receiver)。根据运行时刻,任一候选者都可以响应相应的请求,候选者的数目是任意的,你可以在运行时刻决定哪些候选者参与到链中

还不明白?ok, 来个生活小实例, 早高峰挤公交车,往往挤上去却看不到售票员,我们常常通过他人之手将票钱传递给售票员,这种关系就能看做为职责链,我们的票钱通过多人之手最终递交到售票员手中

代码场景:
假设我们正在开发一个电商网站,某一个商品正在进行预定活动,活动规则如下

500 元定金会收到200 优惠劵
200 元定金会收到100 优惠劵
没有预定的用户只能普通购买
假设我们后端会返回如下字段

orderType [1,2,3] 分别为500,200,普通购买

常规实现:

const order = function(orderType){
  if(orderType===1){
    // 假设我们有其它需求
    if(....){
      .....
    }
    return console.log(500元定金用户)
  }
  if(orderType===2){
    // 假设我们有其它需求
    if(....){
      .....
    }
    return console.log(200元定金用户)
  }
  if(orderType===3){
    // 假设我们有其它需求
    if(....){
      .....
    }
    return console.log(用户普通购买)
  }
}
order(1) // 500元定金用户

虽然我们得到了意料中的运行结果,但这并不是一段优秀的代码,order函数会随着业务的变更经常修改

下面我们用职责链模式进行改写

const Chain = function(fn){
  this.fn = fn;
  this.successor = null;
}
Chain.prototype.setNextSuccessor = function(successor){ 指定在链中的下一个节点
  return this.successor = successor;
}
Chain.prototype.passRequest = function(){  //传递请求给某一下节点
  var ret = this.fn.apply(this,arguments);
  if(ret === false){  // 如果ret 为false 代表链条还得继续往下走
    return this.successor && this.successor.passRequest.apply(this.successor,arguments)
  }
}
// 包装成职责链的节点
var chainOrder500 = new Chain(order500);
var chainOrder200 = new Chain(order200);
// 然后再指定节点在链中的顺序
chainOrder500.setNextSuccessor(chainOrder200)
// 最后把请求传递给第一个节点
chainOrder500.passRequest(1)  // 500元定金用户
用AOP(Aspect Oriented Programming )实现职责链

用AOP实现职责链又简单又巧妙,但这种函数叠加在一起的方式,同时也叠加了函数的作用域,如果链条太长也会对性能造成影响

Function.prototype.after(fn){
  var _this = this;
  return function(){
    var ret = _this.apply(this,arguments);
    if(ret === false){
      return fn.apply(this.arguments);
    }
    return ret
  }
}
var order = order500.after(order200).after(orderNormal);
order(2) // 200定金用户
总结

职责链模式可以很好的帮助我们管理代码,降低发起请求的对象跟接收请求对象的耦合,职责链中的节点顺序是可变化的,我们可以在运行中决定链中包含哪些节点

关于JS每日一题

JS每日一题可以看成是一个语音答题社区
每天利用碎片时间采用60秒内的语音形式来完成当天的考题
群主在次日0点推送当天的参考答案

注 绝不仅限于完成当天任务,更多是查漏补缺,学习群内其它同学优秀的答题思路

点击加入答题

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/103534.html

相关文章

  • JS每日一题如何解es6中的Proxy?

    20190124问: 如何理解es6中的Proxy? 试题解析:对proxy的理解,可能会延伸到vue的双向绑定 Proxy(代理) 定义 可以理解为为目标对象架设一层拦截,外界对该对象的访问,都必须通过这层拦截 简单示例: const obj = new Proxy({}, { get: (target, key, receiver) => { return JS ...

    tinysun1234 评论0 收藏0
  • JS每日一题如何解es6中的Proxy?

    20190124问: 如何理解es6中的Proxy? 试题解析:对proxy的理解,可能会延伸到vue的双向绑定 Proxy(代理) 定义 可以理解为为目标对象架设一层拦截,外界对该对象的访问,都必须通过这层拦截 简单示例: const obj = new Proxy({}, { get: (target, key, receiver) => { return JS ...

    PumpkinDylan 评论0 收藏0
  • 前端知识点(二)

    摘要:在给一个目标对象为构造函数的代理对象构造实例时触发该操作,比如在执行时。 1、元素上下垂直居中的方式有哪些? 元素水平垂直居中的方式有哪些? absolute加margin方案 fixed 加 margin 方案 display:table 方案 行内元素line-height方案 flex 弹性布局方案 transform 未知元素宽高解决方案 absolute加mar...

    zacklee 评论0 收藏0
  • 前端知识点(二)

    摘要:在给一个目标对象为构造函数的代理对象构造实例时触发该操作,比如在执行时。 1、元素上下垂直居中的方式有哪些? 元素水平垂直居中的方式有哪些? absolute加margin方案 fixed 加 margin 方案 display:table 方案 行内元素line-height方案 flex 弹性布局方案 transform 未知元素宽高解决方案 absolute加mar...

    lbool 评论0 收藏0
  • 前端知识点(二)

    摘要:在给一个目标对象为构造函数的代理对象构造实例时触发该操作,比如在执行时。 1、元素上下垂直居中的方式有哪些? 元素水平垂直居中的方式有哪些? absolute加margin方案 fixed 加 margin 方案 display:table 方案 行内元素line-height方案 flex 弹性布局方案 transform 未知元素宽高解决方案 absolute加mar...

    Alex 评论0 收藏0

发表评论

0条评论

lifesimple

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<