职责链设计模式是一种链式调用操作的设计模式,由于其使用可以接收上一个数据,且传递给下一个类型,所以被称为链式调用操作
在我们业务中常见的职责链模式有:作用域链,原型链,DOM节点中的事件冒泡以及处理多个请求的状态下,这些都可以在他们身上看到职责链设计模式
职责链案例
我们来做一个案例,当地汽车经销商做了一个活动,在活动当天缴纳200元汽车定金可在购车时抵1000元,缴纳400元汽车定金可在购车时抵2000元,没有缴纳汽车定金的人只能原价购买汽车,且有可能需要提前预定汽车
如果我们常规去写的情况代码会显得比较冗余,我们通过接收4个参数,再在里面进行判断以此得出最终购车金额或者无库存的时候进行提示
//总金额 库存 定金金额 是否付过定金 function business(amount, stock, depositamt, flag) {// 定金抵扣数据let deposit = [{key: 200,value: 1000}, {key: 400,value: 2000}]// 判断是否缴纳定金以及是否有库存if (flag && stock > 0) {// 判断定金缴纳金额let depositAmount = deposit.filter(R => R.key == depositamt);console.log(`您所购买的车辆原价为${amount}元,折扣后为${amount - depositAmount[0].value}元`);} else {// 判断是否拥有库存if (stock > 0) {console.log(`您所购买的汽车价格为${amount}元!`);} else {// 判断是否缴纳过定金if (flag) {console.log('汽车暂无库存了,您所心仪的车辆到货我们将第一时间通知,请耐心等待');} else {console.log('汽车暂无库存了,需要您先预定,半个月后可来提车');}}}}
使用
business(10000, 1, 200, true)
business(10000, 1, 400, true)
business(10000, 0, 400, true)
business(10000, 1)
business(10000, 0)
如果需求被修改上述做法就不是特别合适,我们可以使用职责链设计模式改造一下,先把每个定金抵扣的函数都抽离出来单独处理,然后再声明一个构造函数以便实现链式调用功能,定金折扣函数结合构造函数进行使用且添加后续执行函数,如果定金函数不能处理则可以返回一个特定的标记,通过该标记进行链式调用
定金折扣函数
//总金额 库存 定金金额 是否付过定金 function depositamt400(amount, stock, depositamt, flag) {// 判断是否拥有库存且交过400块钱定金if (depositamt == 400 && flag && stock) {console.log(`您所购买的车辆原价为${amount}元,折扣后为${amount - (depositamt * 5)}元`);} else {return 'next'}}function depositamt200(amount, stock, depositamt, flag) {// 判断是否拥有库存且交过200块钱定金if (depositamt == 200 && flag && stock) {console.log(`您所购买的车辆原价为${amount}元,折扣后为${amount - (depositamt * 5)}元`);} else {return 'next'}}function orderNormal(amount, stock, depositamt, flag) {// 判断是否有库存if (stock) {console.log(`您所购买的汽车价格为${amount}元!`);} else {// 判断是否缴纳过定金if (flag) {console.log('汽车暂无库存了,您所心仪的车辆到货我们将第一时间通知,请耐心等待');} else {console.log('汽车暂无库存了,需要您先预定,半个月后可来提车');}}}
链式调用构造函数
// 创建一个构造函数class Automobile {constructor(fn) {// 接收一个函数this.fn = fn;//下一个会进行执行的函数this.success = null;}// 设置下一个进行执行的函数setNextSuccess = function (success) { this.success = success;}// 进行执行函数passRequest = function () {// 把当前函数定向到当前实例上面let ret = this.fn.apply(this, arguments)// 判断是否返回继续执行标记if (ret === 'next') {// 继续执行,判断当前是否有继续执行的函数有的话就继续执行并改变其this指向return this.success && this.success.passRequest.apply(this.success, arguments);}}}
使用
//构造函数结构定金函数创建实例 var depositamt400 = new Automobile(depositamt400);var depositamt200 = new Automobile(depositamt200);var orderNormal = new Automobile(orderNormal);
//添加后续根据标记执行函数depositamt400.setNextSuccess(depositamt200);depositamt200.setNextSuccess(orderNormal);
//使用depositamt400.passRequest(10000, 1, 200, true);depositamt400.passRequest(10000, 1, 400, true);depositamt400.passRequest(10000, 0, 400, true);depositamt400.passRequest(10000, 1, 0, false);depositamt400.passRequest(10000, 0, 0, false);
职责链设计模式它只需要知道链式中首个节点就可进行操作,因此减弱了发送者和多个接受者之间的联系,但是并不能保证数据一定会被链式节点处理,也不能保证数据会被所有的链式节点处理
坚持努力,无惧未来!