博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JS设计模式初识(十)-职责链模式
阅读量:6314 次
发布时间:2019-06-22

本文共 3781 字,大约阅读时间需要 12 分钟。

定义

职责链模式的定义是:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。 类似于上级分配给给下级任务...

职责链模式的最大优点:请求发送者只需要知道链中的第一个节点,从而弱化了发送者和一组接收者之间的强联系。我们只需要将硬币传递个面前的人,直到给到售票员手里,算是这个任务结束。如果不使用职责链模式,我就得先搞清楚谁是售票员,才能把硬币递给他。

10.1 订单案例

公司针对支付过定金的用户有一定的优惠政策。

  • 500元定金的用户: 会收到100元的商城优惠券,

  • 200元定金的用户: 可以收到50元的优惠券,

  • 普通用户: 无优惠券,且受到库存的影响

  • 而之前没有支付定金的用户自动降级为普通购买模式,

  • orderType: 1: 500元定金用户, 2: 200元 , 3: 普通用户

  • isPay: 是否支付过 true: 是, false: 否

  • stock 库存量

10.2 实现需求

// 订单函数    function order(orderType, isPay, stock) {        if (orderType === 1) {            if (isPay) {                console.log(' => 500元定金用户, 得到100元优惠券',);            } else {                if (stock > 0) {                    console.log(' => 普通用户, 无优惠券',);                }            }        } else if (orderType === 2) {            if (isPay) {                console.log(' => 200元定金用户, 得到50元优惠券',);            } else {                if (stock > 0) {                    console.log(' => 普通用户, 无优惠券',);                }            }        } else {            if (stock > 0) {                console.log(' => 普通用户, 无优惠券',);            } else {                console.log(' => 库存不足',);            }        }    }    order( 1 , true, 500); // 输出: 500 元定金预购, 得到 100 优惠券复制代码

10.2 改进一下

上面的实现使用了太多的if else 导致代码很乱,很难懂, 下面稍微改进一下

function order500(orderType, isPay, stock) {        if (orderType === 1 && isPay) {            console.log(' => 500元定金用户, 得到100元优惠券',);        } else {            order200(orderType, isPay, stock); // order200 和 order500 耦合在一起        }    }        function order200(orderType, isPay, stock) {        if (orderType === 2 && isPay) {            console.log(' => 200元定金用户, 得到50元优惠券',);        } else {            orderNormal(orderType, isPay, stock);        }    }        function orderNormal(orderType, isPay, stock) {        if (stock > 0) {            console.log(' => 普通用户, 无优惠券',);        } else {            console.log(' => 库存不足',);        }    }复制代码

但是这个函数有个很明显的问题, 就是 order500和order200 是紧紧耦合在一起的

10.3 使用职责链模式改进函数

function Chain(fn) {        this.fn = fn;        this.next = null;    }    Chain.prototype.setNext = function(next) {        return this.next = next;    }    Chain.prototype.passRequest = function(...args) {        let ret = this.fn.apply(this, next);        if (ret === 'successToNext') { // 自动调用下一个函数            return this.next();        }        return ret;    }    // 手动调用下一个    Chain.prototype.next = function() {        return this.next && this.next.apply(this.next, args);    }        // 生成链节点    const ChainOrder500 = new Chain(order500);    const ChainOrder200 = new Chain(order200);    const ChainOrderNormal = new Chain(orderNormal);        // 设置链节点执行顺序    ChainOrder500.setNext(ChainOrder200).setNext(ChainOrderNormal);        // 传给第一个节点    chainOrder500.passRequest( 1, true, 500 );复制代码

通过改进,我们可以自由灵活地增加、移除和修改链中的节点顺序,假如某天网站运营人员 又想出了支持 300 元定金购买,那我们就在该链中增加一个节点即可

var order300 = function(){ // 具体实现略 };    chainOrder300= new Chain(order300);     chainOrder500.setNext(chainOrder300).setNext(chainOrder200);;复制代码

改进之前:

使用职责链改进后:

这个请求或者任务 会在往下传递, 直到有人接手完成了它,否则会一直传递下去,这个类似于 上级给一层层下级传递任务。

10.4 异步的职责链

// 异步职责链    const fn1 = new Chain(() => {        console.log(' => fn1',);        return 'successToNext';    });    const fn2 = new Chain(() => {        console.log(' => fn2',);        // 发送ajax success callback        setTimeout(() => {            this.next();        }, 2000);    });    const fn3 = new Chain(() => {        console.log('fn3 => ',);    });    fn1.setNext(fn2).setNext(fn3);    fn1.passRequest();复制代码

10.5 总结

  • 使用了职责链模式之后,链中的节点对象可以灵活地拆分重组。增加或者删除一个节点,或者改变节点在链中的位置都是轻而易举的事情。这一点我们也已经看到,在上面的例子中, 增加一种订单完全不需要改动其他订单函数中的代码。

  • 实际上只要运用得当,职责链模式可以很好地帮助我们管理代码,降低发起请求的对象和处理请求的对象之间的耦合性。职责链中的节点数量和顺序是可以自由变化的,我们可以在运行时决定链中包含哪些节点。

转载于:https://juejin.im/post/5d04b5326fb9a07ef710718d

你可能感兴趣的文章
ERP环境检测工具设计与实现 Environment Detection
查看>>
不要在构造中做太多事情,不然有时候会出现有意思的代码~
查看>>
IIS 发布网站遇到的问题
查看>>
NuGet学习笔记(2)——使用图形化界面打包自己的类库
查看>>
xcode中没有autoSizing的设置
查看>>
字符编码
查看>>
企业应用:应用层查询接口设计
查看>>
浅谈Excel开发:十 Excel 开发中与线程相关的若干问题
查看>>
nfd指令的详细说明
查看>>
安装VisualSvn Server时遇到的问题
查看>>
不用Visual Studio,5分钟轻松实现一张报表
查看>>
人脸识别 开放书籍 下载地址
查看>>
Notepad++配置Python开发环境
查看>>
用户组概念 和 挂载 概念
查看>>
如何快速获取ADO连接字符串
查看>>
AspNetPager控件的最基本用法
查看>>
sessionKey
查看>>
高性能Javascript--脚本的无阻塞加载策略
查看>>
Java 编程的动态性, 第4部分: 用 Javassist 进行类转换--转载
查看>>
完毕port(CompletionPort)具体解释 - 手把手教你玩转网络编程系列之三
查看>>