从借钱到瞬间理解责任链模式

责任链模式定义:

顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。--菜鸟教程

应用场景:

  1. 有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。
  2. 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求.
  3. 可动态指定一组对象处理请求.

应用案例:

等等,我想想,什么时候对象之间是成串调用的呢?有了

大家回忆一下,在SpringMVC 里面,我们经常用的拦截器(HandlerInterceptor),是不是就是很多个拦截器排着队调用的,SpringMVC中使用HandlerExecutionChain类来将所有的拦截器组装在一起。如果返回ture的话,则交给下一个拦截器处理。

同样的,还有其他web框架的拦截器也有用到责任链设计模式。(你,你这说了不跟没说一样吗)

是的,我想不起来还有哪用到责任链模式了,嗯,就是想不起来

优/缺点:

优点:

  • 降低耦合度。它将请求的发送者和接收者解耦。
  • 简化了对象。使得对象不需要知道链的结构。
  • 增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。
  • 增加新的请求处理类很方便。

缺点:

  • 不能保证请求一定被接收。
  • 系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。
  • 可能不容易观察运行时的特征,有碍于除错。

微剧场:

责任链模式其实在我们平常的生活中有很多地方都可以体现,不要看责任链模式定义这样晦涩难懂,其实本身还是很容易理解的。

责任链模式我把它简单粗暴地概括为4个字:

不行我上

??你有毒吧

不尽然,责任链模式定义是什么,一个接收者对象的链,当一个对象无法处理这类需求的时候,就将它移交给下一个类去处理,如此循环往复,直到有一个对象真正地处理它。

这多像小时候排队打游戏,前面的,你行不行啊,不行我上。

当然,仅仅打游戏这个例子是不足以十分体现责任链模式的本质的,什么时候责任链模式的精髓会被发挥的淋漓尽致呢,当一个和你不是很熟的人向你借钱的时候,请看下面这个小故事,帮助你瞬间理解责任链模式。

最近阿坤,因为给之前斗鱼某乔姓女主播频繁刷礼物手头愈发紧张起来,之前本想着自己多刷点礼物,疯狂按F,女神总有一天会注意到自己的,为了女神委屈一下自己没什么,而且过了十万订阅之后就可以看见女神了。

谁知,她突然....

曾经的18岁美少女萝莉变成58岁萝卜,阿坤一时间分不清梦境与现实,心中一亿只%%%¥%¥%#跑过,可一切已于事无补,想到自己现在钱包空空如也,首要的就是先解决自己的生存问题,可是,因为给女主播刷礼物自己平常没少跟朋友们借钱,而且有很多都没还,也不知道他们还会不会借给我,哎,先试试吧:

阿坤:喂,阿呆啊,我最近手头有点紧,能借我点钱吗?

阿呆:这个,我知道,我也想帮你啊,可是我最近.....,要不你找二呆试试?

阿坤:喂,二呆啊 ...

二呆: ...要不你找三呆试试?

阿坤:喂,三呆吗? ...

三呆:... 要不你找阿凡试试?

....

阿坤:喂,妈,我....

阿坤妈:好,儿子,我现在打给你。

世上只有妈妈好。咳咳。跑题了。

看完这个例子再看概念,是不是瞬间理解责任链模式是何方神圣了。责任链模式每个节点都保留了下一个节点的引用,就跟被借钱的人都告诉阿坤找另外一个人借是一个道理,同样的,如果一个节点不愿意借或者真的没有钱借,就转移给下一个节点处理,直到有节点处理。

这么真实的吗

既然概念理解的差不多了,不废话,我们上代码:

代码实战:

首先,建立我们统一的被借钱的人物模型

public abstract class Handler {
   //是否借钱标志,如果借的话为true
private boolean isBorrow;

public Handler(boolean isBorrow) {
this.isBorrow = isBorrow;
}

//下一个借钱的人
private Handler nextHandler;

public void setNextHandler(Handler nextHandler) {
this.nextHandler = nextHandler;
}

//处理请求传递,用final,防止子类捣乱,禁止子类重写
public final void handleRequest() {

if(isBorrow) {
giveMoney();
}else {
if(null != nextHandler) {
nextHandler.handleRequest();
}

}

}
//借钱
   abstract protected void giveMoney();

}

然后编写相关的子类

//阿呆
public class ADaiHandler extends Handler{


public ADaiHandler(boolean isBorrow) {
super(isBorrow);
// TODO Auto-generated constructor stub
}

@Override
protected void giveMoney() {
System.out.println("这个我还是不借了吧,让他去找二呆吧");

}

}
//二呆
public class ErDaiHandler extends Handler {

public ErDaiHandler(boolean isBorrow) {
super(isBorrow);
// TODO Auto-generated constructor stub
}

@Override
protected void giveMoney() {
System.out.println("这个我是真的没有钱了,让他去找家里人要吧");
}

}
//阿坤的妈妈
public class KunsMontherHandler extends Handler {

public KunsMontherHandler(boolean isBorrow) {
super(isBorrow);
// TODO Auto-generated constructor stub
}

@Override
protected void giveMoney() {
System.out.println("儿子,等一下,妈现在就转给你");

}

}

测试:

public class Test {


public static void main(String[] args) {

ADaiHandler adai = new ADaiHandler(false);
ErDaiHandler erdai = new ErDaiHandler(false);
KunsMontherHandler kunm = new KunsMontherHandler(true);
adai.setNextHandler(erdai);
erdai.setNextHandler(kunm);
adai.handleRequest();

}

}

输出:

儿子,等一下,妈现在就转给你

现在进入最后的技术总结环节:

总结

本篇笔记从一个较为清奇的角度讲了下责任链设计模式,相信看到这里的同学应该已经基本了解了责任链设计模式的本质和代码实现的,没了解的同学请再看一遍(滑稽)。第二个特别是新入门的朋友,不要嫌弃本文废话骚话过多,其实这些废话都是精心编排而成,这样就可以比较容易回想和加深理解。同样的,本文相关文章已经开源至github平台,需要的朋友可以前去下载,听说star可以防止脱发,认真脸。

我是韩数,欢迎大家关注我,我们下篇文章再见!

暂无评论

文艺中二理工男,技术极客程序员

发表评论