JavaScript设计模式_10_职责链模式
职责链模式的定义是:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。职责链模式的名字非常形象,一系列可能会处理请求的对象被连接成一条链,请求在这些对象之间依次传递,直到遇到一个可以处理它的对象,我们把这些对象称为链中的节点。
如下图所示:
/**
* pre:职责链模式
* 定义:一系列可能处理请求的对象链接成一条链,
* 请求在这条链中传递,直到遇到一个可以处理它的对象。
*/
// --------- 示例 1 -----------
/**
* 某品牌手机销售,交500元定金可得100元电商优惠券,交300元可得50元优惠券,
* 没有交定金的用户只能进行普通购买,而且还不一定能买的到。
* 将这一过程用代码写出来:
* orderType: 1,交500定金;2,交300元定金,3,普通购买
* pay:true 已支付定金,false未支付定金
* stock:手机库存数
*/
var order = (function() {
var favorCache = { // 优惠配置
1: [500, 100],
2: [300, 50]
};
var normal = function(stock) { // 普通购买
if(stock > 0) {
console.log("普通购买.库存数:" + stock);
} else {
console.log("库存不足.");
}
};
var preOrder = function(orderType, pay) { // 预付定金
if(orderType in favorCache && pay) {
console.log("支付定金:" + favorCache[orderType][0] + ",获得" + favorCache[orderType][1] + "元优惠券.");
return true;
}
return false;
};
return function(orderType, pay, stock) {
preOrder(orderType, pay) || normal(stock);
}
})();
order(1, true, 500);
order(1, false, 500);
order(2, true, 200);
order(3, false, 100);
order(3, false, 0);
// ------------- 示例2 --------------
/*
* 使用职责链模式实现功能
*/
var order500 = function(orderType, pay, stock) {
if(orderType === 1 && pay) {
console.log("支付定金:500元,获得100元优惠券.");
} else {
order300(orderType, pay, stock);
}
};
var order300 = function(orderType, pay, stock) {
if(orderType === 2 && pay) {
console.log("支付定金:300元,获得50元优惠券.");
} else {
orderNormal(orderType, pay, stock);
}
};
var orderNormal = function(orderType, pay, stock) {
if(stock > 0) {
console.log("普通购买.库存数:" + stock);
} else {
console.log("库存不足.");
}
};
order500(1, true, 500);
order500(1, false, 500);
order500(2, true, 200);
order500(3, false, 100);
order500(3, false, 0);
/**
* 不足:虽然把函数拆分成互不影响的3个小函数,但是传递请求的代码被耦合在业务函数之中,
* 这样的请求传递非常的僵硬,也违背了开放-封闭原则。
*/
//--------------- 示例3 -------------
/**
* 改进上面的职责链模式,让每个节点可以单独拆分和重组.
*/
var order500 = function(orderType, pay, stock) {
if(orderType === 1 && pay) {
console.log("支付定金:500元,获得100元优惠券.");
} else {
return "next";
}
};
var order300 = function(orderType, pay, stock) {
if(orderType === 2 && pay) {
console.log("支付定金:300元,获得50元优惠券.");
} else {
return "next";
}
};
var orderNormal = function(orderType, pay, stock) {
if(stock > 0) {
console.log("普通购买.库存数:" + stock);
} else {
console.log("库存不足.");
}
};
// -- 定义链节点函数 --
var Chain = function(fn) {
this.fn = fn;
this.next = null;
};
Chain.prototype.setNext = function(next) {
this.next = next;
};
Chain.prototype.passRequest = function() {
var result = this.fn.apply(this, arguments);
if("next" === result) {
return this.next && this.next.passRequest.apply(this.next, arguments);
}
return result;
};
var chain500 = new Chain(order500);
var chain300 = new Chain(order300);
var chainNormal = new Chain(orderNormal);
chain500.setNext(chain300);
chain300.setNext(chainNormal); chain500.passRequest(1, true, 500);
chain500.passRequest(1, false, 500);
chain500.passRequest(2, true, 200);
chain500.passRequest(3, false, 100);
chain500.passRequest(3, false, 0);
//---------- 示例4 -----------
/**
* 上个示例中,已经实现了一个职责链模式,但在现实中,我们往往是
* 根据一个异步请求的结果,来决定是否执行下一个函数。
*/
var Chain = function(fn) {
this.fn = fn;
this.next = null;
};
Chain.prototype.setNext = function(next) { // 设置下一个执行函数
return this.next = next;
};
Chain.prototype.passRequest = function() { // 传递请求
var result = this.fn.apply(this, arguments);
if("next" === result) {
return this.next && this.next.passRequest.apply(this.next, arguments);
}
return result;
};
Chain.prototype.executeNext = function() { // 主动执行下一个函数
return this.next && this.next.passRequest.apply(this.next, arguments);
};
var fn1 = new Chain(function() {
console.log(1);
return "next";
});
var fn2 = new Chain(function() {
console.log(2);
var self = this;
setTimeout(function() {
self.executeNext();
}, 2000); // 模拟异步回调
});
var fn3 = new Chain(function() {
console.log(3);
});
fn1.setNext(fn2).setNext(fn3);
fn1.passRequest();
/**
* 经过这些例子,我们总结一下职责链模式的优缺点:
* 优点:
* 1、各个处理函数互不影响,各自独立;
* 2、删除、增加节点比较灵活,不需要改动其他函数的代码;
* 3、可以手动指定起始节点。比如手机商城的例子,付过定金的订单全部结束购买流程后,
* 完全可以把请求交给普通订单处理:orderNormal(1,false,500);
* 缺点:
* 1、我们不能保证某个请求一定会被职责链中的节点处理;
* 2、某些请求被处理时,可能会经历多个节点,会给系统带来性能损耗。
*/
// ----------- 示例5 --------------
/**
* 利用js函数式的特性,创建职责链
*/
Function.prototype.after = function(fn) {
var self = this;
return function() {
var result = self.apply(this, arguments);
if("next" === result) {
return fn.apply(this, arguments);
}
return result;
}
};
var fn1 = function() {
console.log(1);
return "next";
};
var fn2 = function() {
console.log(2);
return "next";
};
var fn3 = function() {
console.log(3);
};
var ff = fn1.after(fn2).after(fn3);
ff();
JavaScript设计模式_10_职责链模式的更多相关文章
- php设计模式之职责链模式
<?php /** * @desc php设计模式之职责链模式(责任链模式) 定义:顾名思义,责任链模式为请求创建了一个接收者对象的链.这种模式给予请求的类型,对请求的发送者和接收者进行解耦.这 ...
- 设计模式之职责链模式(JAVA实现)
学习netty框架时,看到有人说netty用到了设计模式的职责链模式,学习一下职责链模式,主要参考大话设计模式. 主要场景: 小菜想要加薪,向经理提出加薪请求,经理没有权限,经理交由总监处理,总监也没 ...
- 设计模式-利用职责链模式消除if
本文是对职责链设计模式的应用(变种),所以假设读者已经掌握了职责链设计模式,职责链模式只会应景简介. 本文主要内容: 需求(ShitCode) 职责链模式简介 设计理念 代码演示(消除if) 应用总结 ...
- 深入理解JavaScript系列(38):设计模式之职责链模式
介绍 职责链模式(Chain of responsibility)是使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系.将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象 ...
- 设计模式:职责链模式(Chain Of Responsibility)
定 义:使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止. 结构图: 处理请求类: //抽象处理类 abs ...
- 设计模式之职责链模式(Chain of Responsibility)摘录
23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于怎样创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...
- php实现设计模式之 职责链模式
<?php /** * 职责链模式 * * 为解除请求的发送者和接收者之间的耦合,而使用多个对象都用机会处理这个请求,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它 * 抽象 ...
- JS常用的设计模式(15)—— 职责链模式
职责链模式是一个对象A向另一个对象B发起请求,如果B不处理,可以把请求转给C,如果C不处理,又可以把请求转给D.一直到有一个对象愿意处理这个请求为止. 打个比方,客户让老板写个php程序.老板肯定不写 ...
- 设计模式之职责链模式(Chain of Responsibility)
职责链模式原理: 职责链模式和装饰模式以及组合模式类似的地方是都维持着指向父类的指针, 不同点是职责链模式每个子类都继承父类的指针及每个之类都维持着指向父类的指针,而组合模式与装饰模式是组合类鱼装饰类 ...
随机推荐
- HTML5 拖放(Drag 和 Drop)功能开发——基础实战
随着HTML5的普及度越来越高,现在写代码也遇到一些了,经过同事的点播开展了一次Dojo活动用以技术交流,我也乘此机会将HTML5的拖放功能整理了一下. 简介 拖拽(Drag/Drop)是个非常普遍的 ...
- Layui的一点小理解(上)
首先声明这是个人的一点理解,如有不对之处请指正,以下的例子有在官网上看到的,有的是自己写的.还是老规矩最后会附上官网的,如有不明白之处,请查看文档或留言. 既然说Layui,当然要简单的介绍以下什么是 ...
- SQLServer中使用扩展事件获取Session级别的等待信息以及SQLServer 2016中Session级别等待信息的增强
本文出处:http://www.cnblogs.com/wy123/p/6835939.html 什么是等待 简单说明一下什么是等待:当应用程序对SQL Server发起一个Session请求的时候, ...
- iOS 发布证书提示 此证书的签发者无效 解决办法
1. 打开钥匙串 查看发布证书 都是提示 此证书的签发者无效 解决办法 : 2. 到了 第 4 步骤 再去 查看 发布证书 就会 显示 此证书有效 3. 如果还不可以 就 把 Apple W ...
- 如何将网站升级为HTTPS协议?
基本概念: HTTP: 是互联网上应用最为广泛的一种网络协议,是一个客户端和服务器端请求和应答的标准,用于从WWW服务器传输超文本到本地浏览器的传输协议,它可以使浏览器更加高效,使网络传输减少. HT ...
- hdu1520 Anniversary party 简单树形DP
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1520 思路:树形DP的入门题 定义dp[root][1]表示以root为根节点的子树,且root本身参 ...
- Python 基础之基本数据类型
首先,Python中的变量不需要声明.每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建.在Python中,变量就是变量,它没有类型,我们所说的"类型"是变量所指的内存中对象 ...
- PHP平台CMS系统Drupal小试身手----安装教程
最近一直在研究基于Asp.Net MVC的CMS---Orchard,忽然新血来潮,看看多年不看的PHP平台的CMS,那好,就拿Drupal试试身手吧. 第一大招: 环境配置 + 安装. 1.环境配置 ...
- UGUI ScrollRect 性能优化
测试环境 操作系统:Windows8.1 开发工具:Unity5.5.2 1.问题描述,在实际开发过程中经常会使用ScrollRect实现滚动列表,当初次加载数据比较多的情形时,Unity3D会出现比 ...
- Day2-列表、字符串、字典、集合
一.列表 定义列表:通过下标访问列表中的内容,从0开始 >>> name = ["zhang","wang","li",& ...