JS设计模式初识(十)-职责链模式

本文深入解析职责链模式,展示其如何简化请求处理流程,降低系统耦合度。通过实例说明,职责链模式允许请求在对象链中传递,直至被处理,增强了代码的灵活性和可维护性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

定义

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值