JavaScript职责链模式与开发实践(下)

前言

作为一个前端切图仔,少有和各类设计模式打交道。但这不影响我们学习设计模式的思维,来提升我们的代码水平。

本章通过讲解职责链模式,希望能够让你对设计模式更一步的学习。

本章学习内容👇

  • 灵活可拆分的职责链模式

灵活可拆分的职责链模式

在上一章,《JavaScript职责链模式与开发实践(中)》

我们将大段的条件判断函数拆分为了三个小函数,并用职责链模式模式串联起来了这些模块。虽然解决了大量使用条件分支的语句,但这依然还存在一些问题:

function orderMember(seniorMember, price) {
    if (seniorMember) {
       return orderSeniorMember(price)
    } else {
        return price * 0.95
    }
}

可以看到,在职责链的传递上非常僵硬,链上的下一段函数直接被耦合在了业务函数之中。这是违反开放-封闭原则OCP,Open Closed Principle)是所有面向对象原则的核心。如果以后我们的会员还要再分钻石会员以及大会员等等就意味着必须改动这些业务函数内部。这会扰乱我们之前所构建的链条,就像在已经创建好的数组我们去改变其中每一个元素的顺序而导致整个数组偏移的后果。

接下来, 我们通过对职责链节点进行一层工厂化包装来解决这个问题👇

首先,我们先解除之前三个函数节点的耦合。并在需要传递给下一层请求时,我们通过返回一个字符串nextSuccessor表示。

​
function orderNormal(userType, seniorMember, stock, price) {
    if (userType === 0) {
        if (stock > 0) {
            console.log(price * 0.99)
        } else {
            console.log(false)
        }
    } else {
        return 'nextSuccessor'; //向职责链后继节点传递请求
    }
}
​
function orderMember(userType, seniorMember, stock, price) {
    if (seniorMember == 0) {
        return 'nextSuccessor'; //向职责链后继节点传递请求
    } else {
        console.log(price * 0.95)
    }
}
​
function orderSeniorMember(userType, seniorMember, stock, price) {
    if (userType === 1 && seniorMember == 1) {
         console.log(price * 0.91)
    }
}
​

接着, 我们定义一个构造函数Chain,使它接受一个函数作为该节点运行的函数,同时他还拥有俩个属性和方法:

  • fn当前的运行节点函数
  • successor下一个节点
  • Chain.prototype.setNextSuccessor指定在链中的下一个节点
  • Chain.prototype.passRequest传递请求给某个节点
let 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 === 'nextSuccessor') {
        return this.successor && this.successor.passRequest.apply(this.successor, arguments);
    }
    return ret;
};

然后, 我们通过这个工厂实例化包装下我们的节点,并测试运行。

var chainOrderSenior = new Chain(orderSeniorMember);
var chainOrderMember = new Chain(orderMember);
var chainOrderNormal = new Chain(orderNormal);
​
chainOrderMember.setNextSuccessor(chainOrderSenior);
chainOrderNormal.setNextSuccessor(chainOrderMember);
​
chainOrderNormal.passRequest(1, false, 1, 100)

控制台输出

95

完成🤩。这样下次我们需要追加新的会员等级或者其他条件时,只需要设置在对应节点设置后继节点即可。

\

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值