设计模式 2(职责链模式)

问题抛出:

双十一马上到了,一年一度的促销大战一触即发。于是我司特推出“预交订金购买手机,送代金券活动”。

活动如下:预交500元,送100元代金卷,预交200元,送50元代金卷。

根据本活动内容,让我司前端同学,给出编码提示:

一个刚入司的小A同学,感觉没有什么困难,写出如下代码

/***
** orderType 表示订单类型
** pay 表示用户是否已经支付定金
** stock 表示普通购买的手机库存数量
*/
const order = function (orderType, pay, stock) {
    if (orderType === 1) {
        if (pay === true) {
            console.log('500元定金预购,得到100元优惠券')
        } else {
            if (stock > 0) {
                console.log('普通用户购买,无优惠券')
            } else {
                console.log('手机库存不足')
            }
        }
    } else if (orderType === 2) {
        if (pay === true) {
            console.log('200元定金购买,得到50元优惠卷')
        } else {
            if (stock > 0) {
                console.log('普通购买,五优惠卷')
            } else {
                console.log('手机库存不足')
            }
        }
    } else if (orderType === 3) {
        if (stock > 0) {
            console.log('普通用户购买,无优惠券')
        } else {
            console.log('手机库存不足')
        }
    }
}
order(1,true,500)

小B同学,阅读了小A的同学的代码后,感觉代码耦合性太高。如果需求一有变动,就需要重新修改上面的代码。于是写出了自己的代码如下:

/***
** orderType 表示订单类型
** pay 表示用户是否已经支付定金
** stock 表示普通购买的手机库存数量
*/
const order500 = function (orderType, pay, stock) {
    if (orderType === 1 && pay === true) {
        console.log('500元定金预购,得到100元代金券')
    } else {
        order200(orderType, pay, stock);
    }
}
const order200 = function (orderType, pay, stock) {
    if (orderType === 2 && pay === true) {
        console.log('200元定金购买,得到50元代金券')
    } else {
        orderNormal(orderType, pay, stock)
    }
}
const orderNormal = function (orderType, pay, stock) {
    if (stock > 0) {
        console.log('普通购买,无优惠卷')
    } else {
        console.log('手机库存不足')
    }
}

//测试结果
order500(1, true, 500)
order500(1, false, 500)
order500(2, true, 500)
order500(3, false, 500)
order500(3, false, 0)

小C同学看了小B的代码后,感觉比小A的同学便于阅读了,但是感觉还是没有完全解耦,order500中含有order200的调用。请求在链条传递中的顺序比较僵硬,传递请求的代码还是耦合再来业务函数中,依然违反开放-封闭原则,如果有一天要增加哦300元预订或者去掉200元预定,意味着就必须修改业务函数内部。我们能不能灵活拆分掉他们呢?小C同学在小B的基础上,做了如下修改

/***
** orderType 表示订单类型
** pay 表示用户是否已经支付定金
** stock 表示普通购买的手机库存数量
*/
const order500 = function (orderType, pay, stock) {
    if (orderType === 1 && pay === true) {
        console.log('500元定金预购,得到100元代金券')
    } else {
        return 'nextSuccessor'
    }
}
const order200 = function (orderType, pay, stock) {
    if (orderType === 2 && pay === true) {
        console.log('200元定金购买,得到50元代金券')
    } else {
        return 'nextSuccessor'
    }
}
const orderNormal = function (orderType, pay, stock) {
    if (stock > 0) {
        console.log('普通购买,无优惠卷')
    } else {
        console.log('手机库存不足')
    }
}

//测试结果
const Chain = function (fn) {
    this.fn = fn;
    this.successor = null;
}
// 指定链条中的下一个环节
Chain.prototype.setNextSuccessor = function (successor) {
    return this.successor = successor
}
// 传递请求给下一个节点
Chain.prototype.passRequest = function () {
    const ret = this.fn.apply(this, arguments)
    if (ret === 'nextSuccessor') {
        return this.successor && this.successor.passRequest.apply(this.successor, arguments)
    }
    return ret
}

const chinaOrder500 = new Chain(order500);
const chainOrder200 = new Chain(order200);
const chainOrderNormal = new Chain(orderNormal)

// chinaOrder500.setNextSuccessor(chainOrder200);
// chainOrder200.setNextSuccessor(chainOrderNormal);

chinaOrder500.setNextSuccessor(chainOrder200).setNextSuccessor(chainOrderNormal)


chinaOrder500.passRequest(1, true, 500);
chinaOrder500.passRequest(2, true, 500);
chinaOrder500.passRequest(3, true, 500);
chinaOrder500.passRequest(1, false, 0);

小C将自己的代码提交给主管,主管感觉写的停不错。业务与代码解耦了,链接灵活性高。

JavaScript有它天然的独特性,我们可以利用高阶函数的思想也能实现上面的业务。

/***
** orderType 表示订单类型
** pay 表示用户是否已经支付定金
** stock 表示普通购买的手机库存数量
*/
const order500 = function (orderType, pay, stock) {
    if (orderType === 1 && pay === true) {
        console.log('500元定金预购,得到100元代金券')
    } else {
        return 'nextSuccessor'
    }
}
const order200 = function (orderType, pay, stock) {
    if (orderType === 2 && pay === true) {
        console.log('200元定金购买,得到50元代金券')
    } else {
        return 'nextSuccessor'
    }
}
const orderNormal = function (orderType, pay, stock) {
    if (stock > 0) {
        console.log('普通购买,无优惠卷')
    } else {
        console.log('手机库存不足')
    }
}


Function.prototype.after = function (fn) {
    const self = this;
    return function () {
        const ret = self.apply(this, arguments);
        if (ret === 'nextSuccessor') {
            return fn.apply(this, arguments)
        }
        return ret;
    }
}

const order = order500.after(order200).after(orderNormal);

order(1, true, 500)
order(2, true, 500)
order(1, false, 500)

我们还可以实现异步的职责链



//测试结果
const Chain = function (fn) {
    this.fn = fn;
    this.successor = null;
}

Chain.prototype.setNextSuccessor = function (successor) {
    return this.successor = successor
}
Chain.prototype.passRequest = function () {
    const ret = this.fn.apply(this, arguments)
    if (ret === 'nextSuccessor') {
        return this.successor && this.successor.passRequest.apply(this.successor, arguments)
    }
    return ret
}
// 异步的职责链
Chain.prototype.next = function () {
    return this.successor && this.successor.passRequest.apply(this.successor, arguments)
}


const fn1 = new Chain(function () {
    console.log(1)
    return 'nextSuccessor'
})
const fn2 = new Chain(function () {
    console.log(2)
    const self = this
    setTimeout(() => {
        self.next()
    }, 1000)
})
const fn3 = new Chain(function () {
    console.log(3)
})
// 链式调用
fn1.setNextSuccessor(fn2).setNextSuccessor(fn3);
fn1.passRequest()

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值