Javascript设计模式之职责链模式

342 阅读3分钟

前言:菜鸡也有梦想,而我的梦想就是进一个真正的互联网大厂。以前学习的时候没有系统的整理,从今天开始要保持每周写博客的习惯,希望自己可以有所成长。为了培养编程思维,决定从设计模式开始写起。我是通过读《Javascript设计模式与开发实践》来学习设计模式,并且将知识点和收获记录在博客中。

此文仅记录本人阅读《JavaScript设计模式与开发实践》的知识点与想法,感谢作者曾探大大写出这么好的一本书。如有冒犯,请联系本人:markcoder@outlook.com处理,请大家购买正版书籍。

1.职责链模式介绍

多个对象均有机会处理请求,从而解除发送者和接受者之间的耦合关系。这些对象连接成为链式结构,每个节点转发请求,直到有对象处理请求为止。

2.优缺点

2.1优点

1.可以根据需求变动,任意向责任链中添加或删除节点对象

2.有固定的“开始节点”,可以从任意节点开始

2.2缺点

责任链最大的代价就是每个节点带来的多余消耗。当责任链过长,很多节点只有传递的作用,而不是真正地处理逻辑。

3.代码实现

在此使用书中的例子:公司针对支付过定金的用户有一定的优惠政策。在正式购买后,已经支付过 500 元定金的用户会收到 100 元的商城优惠券,200 元定金的用户可以收到 50元的优惠券,而之前没有支付定金的用户只能进入普通购买模式,也就是没有优惠券,且在库存有限的情况下不一定保证能买到。

orderType:表示订单类型(定金用户或者普通购买用户),code 的值为 1 的时候是 500 元 定金用户,为 2 的时候是 200 元定金用户,为 3 的时候是普通购买用户。

pay:表示用户是否已经支付定金,值为 true 或者 false, 虽然用户已经下过 500 元定金的 订单,但如果他一直没有支付定金,现在只能降级进入普通购买模式。

stock:表示当前用于普通购买的手机库存数量,已经支付过 500 元或者 200 元定金的用 户不受此限制

let order500 = (orderType, pay, stock) => {
    if (orderType === 1 && pay === true) {
        console.log('500 元定金预购,得到 100 优惠券');
    } else {
        return 'nextSuccessor'; // 传递请求给下一个节点
    }
}

let order200 = (orderType, pay, stock) => {
    if (orderType === 2 && pay === true) {
        console.log('200 元定金预购,得到 50 优惠券');
    } else {
        return 'nextSuccessor'; // 传递请求给下一个节点
    }
}

let orderNormal = (orderType, pay, stock) => {
    if (stock > 0) {
        console.log( '普通购买,无优惠券' );
    } else {
        console.log( '库存不足' );
    }
}

class Chain {
    constructor (fn) {
        this.fn = fn;
        this.successor = null;
    }
    
    setNextSuccessor (successor) {
        return this.successor = successor;
    }
    
    passRequest () {
        let ret = this.fn.apply(this, arguments);
        
        if (ret === 'nextSuccessor') {
            return this.successor && this.successor.passRequest.apply(this.successor, arguments);
        }
        
        return ret;
    }
}

// 现在我们把 3 个订单函数分别包装成职责链的节点
let chainOrder500 = new Chain( order500 ); 
let chainOrder200 = new Chain( order200 ); 
let chainOrderNormal = new Chain( orderNormal );

// 然后指定节点在职责链中的顺序
chainOrder500.setNextSuccessor( chainOrder200 ); 
chainOrder200.setNextSuccessor( chainOrderNormal );

chainOrder500.passRequest( 1, true, 500 ); // 输出:500 元定金预购,得到 100 优惠券
chainOrder500.passRequest( 2, true, 500 ); // 输出:200 元定金预购,得到 50 优惠券
chainOrder500.passRequest( 3, true, 500 ); // 输出:普通购买,无优惠券
chainOrder500.passRequest( 1, false, 0 ); // 输出:手机库存不足