声明:这个系列为浏览《JavaScript设想形式与开辟实践》 —-曾探@著一书的读书笔记
1.职责链形式的定义
使多个对象都有时机处置惩罚要求,从而防止要求的发送者和接收者之间的耦合关联,将这些对象连成一条链,并沿着这条链通报该要求,直到有一个对象处置惩罚它为止。
2.
2.1 简朴职责链形式
故事背景:用户能够付出定金购置手机,而且能够获得优惠券。没有付出定金的就是一般用户,进入一般购置形式,没有优惠券,且库存不足的状况下不肯定能够买到手机。
/**
*
* @param orderType 定单范例
* @param pay 用户是不是已付出过定金 true or false
* @param stock 示意手机的库存量
*/
var 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('手机库存不足');
}
}
};
2.2职责链重构上面的代码
重要经由过程拆分功用语句,来应用职责链重构:
//500元定单
var order500 = function (orderType, pay, stock){
if (orderType === 1 && pay === true) {
console.log('500定金预购,获得100元优惠券');
}
else {
order200(orderType, pay, stock); //将要求通报给200
}
};
//200元定单
var order200 = function (orderType, pay, stock){
if (orderType === 2 && pay === true) {
console.log('200定金预购,获得50元优惠券');
}
else {
order(orderType, pay, stock);
}
};
//一般购置定单
var order = function (orderType, pay, stock){
if (stock>0) {
console.log('一般购置,没有优惠券');
}
else {
console.log('手机库存不足');
}
};
//测试挪用
order500(1,true,500);
order500(3,false,0);
总结:
上面的代码违反了开放-关闭的准绳,要求在链条中通报的递次异常生硬,通报要求的代码被耦合在了营业函数中:
var order500 = function (orderType, pay, stock){
if (orderType === 1 && pay === true) {
console.log('500定金预购,获得100元优惠券');
}
else {
order200(orderType, pay, stock); //将要求通报给200
}
};
2.3天真的拆分职责链节点
为何要拆分职责链的节点,由于某天须要增添新的职责,就须要修正营业代码(要修正的话,就须要先去相识他,熟习它,消费大批的时候)。这明显不是每一个人所须要的。
//500元定单
var order500 = function (orderType, pay, stock){
if (orderType === 1 && pay === true) {
console.log('500定金预购,获得100元优惠券');
}
else {
return 'nextSuccessor';
}
};
//200元定单
var order200 = function (orderType, pay, stock){
if (orderType === 2 && pay === true) {
console.log('200定金预购,获得50元优惠券');
}
else {
return 'nextSuccessor';
}
};
//一般购置定单
var order = function (orderType, pay, stock){
if (stock>0) {
console.log('一般购置,没有优惠券');
}
else {
console.log('手机库存不足');
}
};
var Chain=function (fn){
this.fn=fn;
this.successor=null;
};
Chain.prototype.setNextSuccessor=function (successor){
return this.successor=successor;
};
Chain.prototype.passRequest=function(){
var ret= this.fn.apply(this,arguments);
if(ret==='nextSuccessor'){
return this.successor && this.successor.passRequest.apply(this.successor,arguments);
}
return ret;
};
var chainOrder500=new Chain(order500());
var chainOrder200=new Chain(order200());
var chainOrderNormal=new Chain(order());
chainOrder500.setNextSuccessor(chainOrder200);
chainOrder200.setNextSuccessor(chainOrderNormal);
chainOrder500.passRequest(1,true,500);
chainOrder500.passRequest(2,true,500);
chainOrder500.passRequest(1,false,0);
到场某天网站增添了300元定金购置的职责,我只须要增添特定的节点就能够了:
//300元定单
var order300=function (){
};
var chainOrder300=new Chain(order300());
chainOrder500.setNextSuccessor(chainOrder300);
chainOrder500.setNextSuccessor(chainOrder200);
如许的话只须要编写简朴的功用函数,转变职责链中的相干节点的递次即可。
3.异步职责链
上面的职责链代码中,每一个节点函数同步返回一个特定的值nextSuccessor
,来示意是不是把要求通报给下一个节点。而实际开辟中会碰到一些异步的题目,比如在一个节点中提议一个ajax
异步要求,异步要求的效果才决议是不是继承在职责链中passRequest
。
能够给Chain
类增添一个原型要领Chain.prototype.next
,示意手动通报要求给职责链中的下一个节点:
Chain.prototype.next=function(){
return this.successor && this.successor.passRequest.apply(this.successor,arguments);
};
//异步职责链的例子
var fn1=new Chain(function (){
console.log(1);
return 'nextSuccessor';
});
var fn2=new Chain(function (){
console.log(2);
var self=this;
setTimeout(function (){
self.next();
},1000);
});
var fn3=new Chain(function (){
console.log(3);
});
fn1.setNextSuccessor(fn2).setNextSuccessor(fn3);
fn1.passRequest();
4.职责链形式的优瑕玷:
长处:
职责链最大的长处就是解耦了要求发送者和N个接收者之间的复杂关联。
职责链能够手动指定肇端节点,要求并非非得从链中的第一个节点最先通报。
瑕玷:
不能保证某个要求肯定会被链中的节点处置惩罚,这类状况能够在链尾增添一个保底的接受者节点来处置惩罚这类行将脱离链尾的要求。
使顺序中多了许多节点对象,能够再一次要求的过程当中,大部分的节点并没有起到实质性的作用。他们的作用仅仅是让要求通报下去,从机能劈面斟酌,要防止太长的职责链到来的机能消耗。
5.应用AOP(面向切面编程)来疾速的建立职责链
AOP的详细观点能够参考装潢者形式
Function.prototype.after=function(fn){
var self=this;
return function(){
var ret=self.apply(this,arguments);
if(ret==='nextSuccessor'){
return fn.apply(this,arguments);
}
return ret;
}
};
var order=order500yuan.after(order200yuan).after(orderNormal);
order(1,true,500);
order(1,false,500);
AOP完成职责链简朴又奇妙,但这类把函数叠在一同的体式格局,同时也叠加了函数的作用域,假如链条太长的话,也会对机能形成太大的影响。
总结:
职责链形式最大的长处:要求发送者只须要知道链中的第一个节点,从而弱化了发送者和一组接收者之前的强联络。
在JavaScript开辟中,职责链形式是最轻易被忽视的形式之一。然则只需应用妥当,职责链形式能够很好的协助我们治理代码,下降提议要求的对象和处置惩罚要求的对象之间的耦合性。且职责链中节点的数目和数序是能够自在变化的。能够在运行时决议链中包括哪些节点。
无论是作用域链,原型链,照样DOM节点中的事宜冒泡,我们都能从中找到职责链形式的影子。