使多个对象都有机会处理请求,避免发送者和接收者之间的耦合关系,将这些对象连成一条链,并沿着这条链条传递该请求,直到一个对象处理它为止。
-
场景
商场优惠券, 预交500 得 100, 预交 300 得 50, 提前付钱就一定有货, 没付自动为普通用户,并且可能会由于没有库存不给发货。
function order(orderType, pay, stock) { if (orderType == 1) { if (pay) { console.log('获得100优惠券') } else { console.log('变成普通用户') if (!stock) { console.log('没有库存了') } } } if (orderType == 2) { if (pay) { console.log('获得50优惠券') } else { console.log('变成普通用户') if (!stock) { console.log('没有库存了') } } } if (orderType == 3) { console.log('普通用户') if (!stock) { console.log('没有库存了') } } } order(2, true, 0); //结果: 获得50优惠券上述写法代码冗余太多,if判断太多。
function doOne(orderType, pay, stock) {
if (pay && orderType == 1) {
console.log('500优惠')
} else {
doTwo(orderType,pay, stock)
}
}
function doTwo(orderType, pay, stock) {
if (pay && orderType == 2) {
console.log('300优惠')
} else {
doThree(orderType,pay, stock)
}
}
function doThree(orderType, pay, stock) {
if (orderType == 3)
console.log('普通用户')
if (!stock) {
console.log('没有库存了')
}
}
doOne(2, true, 0);
优点: 减少了很多if,但依然违背开放-封闭原则。
改,面向对象:
var orderNum = function (fn) {
this.fn = fn;
this.next = null;
}
orderNum.prototype.nextFun = function (next) {
return this.next = next;
}
orderNum.prototype.todoNext = function () {
let res = this.fn.apply(this, arguments);
if (res === 'noSuccess') {
return this.next && this.next.todoNext.apply(this.next, arguments)
}
}
function onOne(type, pay, stock) {
if (type == 1 && pay) {
console.log('获得100优惠')
} else {
return 'noSuccess'
}
}
function onTwo(type, pay, stock) {
if (type == 2 && pay) {
console.log('获得50优惠')
} else {
return 'noSuccess'
}
}
function onThree(type, pay, stock) {
console.log('普通用户')
if (!stock) {
console.log('没有库存')
}
}
var one = new orderNum(onOne);
var two = new orderNum(onTwo);
var three = new orderNum(onThree);
one.nextFun(two);
two.nextFun(three)
one.todoNext(1,true,500) //获得100优惠
one.todoNext(2,true,500) //获得50优惠
one.todoNext(3,true,500) //普通用户
上述例子,优点: 易扩展,不用修改原来代码结构。 缺点: 太重。
- 改成异步
var orderNum = function (fn) {
this.fn = fn;
this.next = null;
}
orderNum.prototype.nextFun = function (next) {
return this.next = next;
}
orderNum.prototype.todoNext = function () {
let res = this.fn.apply(this, arguments);
if (res === 'noSuccess') {
return this.next && this.next.todoNext.apply(this.next, arguments)
}
}
orderNum.prototype.nextTo = function () { //新增手动执行下一步方法
return this.next && this.next.todoNext.apply(this.next, arguments)
}
function onOne(type, pay, stock) {
if (type == 1 && pay) {
console.log('获得100优惠')
} else {
setTimeout(() => {
this.nextTo(type,pay,stock) //手动控制下一步
}, 2000)
// return 'noSuccess'
}
}
function onTwo(type, pay, stock) {
if (type == 2 && pay) {
console.log('获得50优惠')
} else {
return 'noSuccess'
}
}
function onThree(type, pay, stock) {
console.log('普通用户')
if (!stock) {
console.log('没有库存')
}
}
var one = new orderNum(onOne);
var two = new orderNum(onTwo);
var three = new orderNum(onThree);
one.nextFun(two).nextFun(three)
one.todoNext(2, false, 500)
3.aop写法
function onOne(type, pay, stock) {
if (type == 1 && pay) {
console.log('获得100优惠')
} else {
return 'noSuccess'
}
}
function onTwo(type, pay, stock) {
if (type == 2 && pay) {
console.log('获得50优惠')
} else {
return 'noSuccess'
}
}
function onThree(type, pay, stock) {
console.log('普通用户')
if (!stock) {
console.log('没有库存')
}
}
Function.prototype.before = function (before) {
var _self = this;
return function () {
before.apply(this, arguments);
return _self.apply(this, arguments)
}
}
Function.prototype.after = function (after) {
var _self = this;
return function () {
var res = _self.apply(this, arguments);
if (res == 'noSuccess')
return after.apply(this, arguments);
}
}
var order = onOne.after(onTwo).after(onThree);
order(1,true,200) //获得100优惠