定义
职责链模式 (Chain of responsibility) 是使多个对象都有机会处理请求, 从而避免请求的发送者和接受者之间的耦合关系. 将这个对象连成一条链, 并沿着这条链传递该请求, 直到有一个对象处理他为止
简而言之, 请求以后, 从第一个对象开始, 链中收到请求的对象要么亲自处理它, 要么转发给链中的下一个候选者. 提交请求的对象并不明确知道哪一个对象将会处理它 -- 也就是该请求有一个隐式的接受者(implicit receiver). 根据运行时刻, 任一候选者都可以响应相应的请求, 候选者的数目是任意的, 可以在运行时刻决定哪些候选者参与到链中
核心思想
请求者不必知道是谁哪个节点对象处理的请求. 如果当前不符合终止条件, 那么把请求转发给下一个节点处理
职责链模式是一种对象行为型模式
场景
1000 + 万人口的新一线城市 , 以早高峰公交为例, 早上早高峰的时候通常都是公交车前门拥堵, 以至于没办法刷卡乘车; 但是后门相对来说会空一些, 这时只能选择后门上车, 但是后门上车就刷不了卡, 逃单? 不存在的, 这可不是作为讲文明, 有素质的新一代青年应该做的, 于是, 只能往前面传递公交卡, 请求前面的乘客帮忙传递至刷卡器处刷卡, 但是在后门, 刷卡器是在前门, 这传递的过程中会通过请求多位乘客帮忙传递公交卡, 这个传递的过程就是一种职责链模式, 每一位传递的乘客就是职责链中的节点对象
特性
而当需求具有 "传递" 的性质时(代码中其中一种体现就是: 多个 if,else if,else if,else 嵌套), 就可以考虑将每个分支拆分成一个节点对象, 拼接成为责任链
适用性
如果有多个对象可以处理同一个请求, 但是具体由哪个对象来处理该请求, 是运行时刻动态确定的
这种情况可以使用职责链模式, 把处理请求的对象实现成为职责对象, 然后把它们构成一个职责链, 当请求在这个链中传递的时候, 具体由哪个职责对象来处理, 会在运行时动态判断
如果你想在不明确指定接收者的情况下, 向多个对象中的一个提交一个请求的话, 可以使用职责链模式
职责链模式实现了请求者和接收者之间的解耦, 请求者不需要知道究竟是哪一个接收者对象来处理了请求
如果想要动态指定处理一个请求的对象集合, 可以使用职责链模式, 职责链模式能动态的构建职责链
也就是动态的来决定到底哪些职责对象来参与到处理请求中来, 相当于是动态指定了处理一个请求的职责对象集合
式例
- const Circle = function() {
- this.radius = 0
- this.drawByRadius = function(radius) {
- if(radius < 5) {
- this.drawVerySmalCircle()
- }else if(radius < 10) {
- this.drawSmalCircle()
- }else if(radius < 15) {
- this.drawMediumCircle()
- }else if(radius < 20) {
- this.drawBigCircle()
- }else{
- this.drawVeryBigCircle()
- }
- }
- this.drawVerySmalCircle = function() {
- console.log('画一个超小的圆( 5 以下 )')
- }
- this.drawSmalCircle = function() {
- console.log('画一个小圆( 5-10 )')
- }
- this.drawMediumCircle = function() {
- console.log('画一个中圆 ( 10-15 )')
- }
- this.drawBigCircle = function() {
- console.log('画一个大圆 ( 15-20 )')
- }
- this.drawVeryBigCircle = function() {
- console.log('画一个超大的圆 ( 20 以上 )')
- }
- }
- const circle = new Circle();
- circle.drawByRadius(30) // 画一个超大的圆 ( 20 以上 )
观察上面的代码, 这是很常见的逻辑, 通过参数来决定执行哪个方法. 首先 drawByRadius 方法职责过重, 其次这样的方式在修改, 新增时需要修改源代码, 不符合开关原则使用职责链模式重写
- const drawSmalCircle = function(min, max) {
- this.max = max
- this.min = min
- this.nextCircle
- this.setNextDraw = function(circle) {
- this.nextCircle = circle
- }
- this.draw = function(radius) {
- console.log('执行: drawSmalCircle')
- if(this.min < radius && radius < this.max) {
- console.log('画一个小圆( 10 以下 )')
- }
- if(this.nextCircle) {
- this.nextCircle.draw(radius)
- }
- }
- }
- const drawMediumCircle = function(min, max) {
- this.max = max
- this.min = min
- this.nextCircle
- this.setNextDraw = function(circle) {
- this.nextCircle = circle
- }
- this.draw = function(radius) {
- console.log('执行: drawMediumCircle')
- if(this.min < radius && radius < this.max) {
- console.log('画一个中圆 ( 10-20 )')
- }
- if(this.nextCircle) {
- this.nextCircle.draw(radius)
- }
- }
- }
- const drawBigCircle = function(min, max) {
- this.max = max
- this.min = min
- this.nextCircle
- this.setNextDraw = function(circle) {
- this.nextCircle = circle
- }
- this.draw = function(radius) {
- console.log('执行: drawBigCircle')
- if(this.min < radius && radius < this.max) {
- console.log('画一个大圆 ( 20 以上 )')
- }
- if(this.nextCircle) {
- this.nextCircle.draw(radius)
- }
- }
- }
- function initChain() {
- const smalCircle = new drawSmalCircle(0, 10)
- const mediumCircle = new drawMediumCircle(10, 20)
- const bigCircle = new drawBigCircle(20, 100)
- smalCircle.setNextDraw(mediumCircle)
- mediumCircle.setNextDraw(bigCircle)
- return smalCircle
- }
- const circle = initChain()
- circle.draw(30)
- // 执行: drawSmalCircle
- // 执行: drawMediumCircle
- // 执行: drawBigCircle
- // 画一个大圆 ( 20 以上 )
- circle.draw(15)
- // 执行: drawSmalCircle
- // 执行: drawMediumCircle
- // 画一个中圆 ( 10-20 )
- // 执行: drawBigCircle
- circle.draw(5)
- // 执行: drawSmalCircle
- // 画一个小圆( 10 以下 )
- // 执行: drawMediumCircle
- // 执行: drawBigCircle
以上就是职责链模式的实例代码, drawSmalCircle,drawMediumCircle,drawBigCircle 称为处理者类, 处理者类保存了下一级对象的引用当每执行一次 draw 时, 程序会挨个执行职责链上的每一个方法职责链模式分为纯职责链和不纯职责链, 纯的职责链在处理请求时, 只能选择全部处理不传递或者全部传递不处理. 这里的例子就是不纯职责链. 它允许处理完成后继续向后传递
优缺点
优点
降低耦合度, 在职责链模式里面, 请求者并不知道接收者是谁, 也不知道具体如何处理, 请求者只是负责向职责链发出请求就可以了. 接收者和请求者都没有对象的明确的信息, 且链中的对象不需要知道链的结构. 结果是, 职责链可简化接收者对象的相互连接. 它们仅需保持一个指向其后续者的引用, 而不需要保持它所有的候选接收者的引用
增强了给对象指派职责的灵活性, 当在接收者中分派职责时, 职责链给你更多的灵活性. 你可以通过在运行时刻对该链进行动态的增加或修改来增加或改变处理一个请求的那些职责
缺点
不保证被接受, 既然一个请求没有明确的接收者, 那么就不能保证它一定会被处理 -- 该请求可能一直到链的末端都得不到处理, 一个请求也可能因该链没有正确配置而得不到处理
带来多余消耗, 当责任链过长, 很多节点只有传递的作用, 而不是真正地处理逻辑
建链不当, 会造成循环调用, 导致系统陷入死循环
来源: http://www.bubuko.com/infodetail-3653334.html