简介
普通的 if else 或者 switch case 语句虽然可以做选择,但是一旦条件增加,就显得混乱。责任链模式的的思想其实和 if else 或者 switch case 很类似都是一步步做过滤,只不过责任链是通过对象来过滤罢了,责任链可以看做一条单链表的数据结构,一个对象一个对象的过滤条件,符合的就执行然后结束,不符合的就往后传递,如果每个对象都无法处理,一般会有一个最终的处理器来处理
代码实现
我们先看故事场景
假如你朋友有一辆豪车,但是它坏掉了,朋友委托你帮他找原厂家修理,可是你是一个车盲,不知道这是哪个牌子的车,可能是宾利,劳斯莱斯,兰博基尼?你只能一家家的打电话询问
// 处理请求的责任链结点
public abstract class Handler {
// 后继结点
public Handler successor;
// 如何处理请求
public abstract void handlerRequest(String car);
// set successor
public void setSuccessor(Handler successor) {
this.successor = successor;
}
}
// 宾利 Handler 1
public class BentleyHandler extends Handler {
@Override
public void handlerRequest(String car) {
if (car.equals("宾利")) {
System.out.println("这里是宾利公司,可以修理宾利汽车");
}
else {
successor.handlerRequest(car);
}
}
}
// 劳斯莱斯 Handler 2
public class RollsRoyceHandler extends Handler {
@Override
public void handlerRequest(String car) {
if (car.equals("劳斯莱斯")) {
System.out.println("这里是劳斯莱斯公司,可以修理劳斯莱斯汽车");
}
else {
successor.handlerRequest(car);
}
}
}
// 兰博基尼 Handler 3
public class LamborghiniHandler extends Handler {
@Override
public void handlerRequest(String car) {
if (car.equals("兰博基尼")) {
System.out.println("这里是兰博基尼公司,可以修理兰博基尼汽车");
}
else {
successor.handlerRequest(car);
}
}
}
// 终极处理器 Handler 4
public class OthersHandler extends Handler {
@Override
public void handlerRequest(String car) {
System.out.println("不知道汽车类型,还没有公司能处理这款车");
}
}
// 主函数入口
public class Demo {
public static void main(String[] args) {
// 责任链中的各个对象
Handler bentley = new BentleyHandler();
Handler rollsRoyce = new RollsRoyceHandler();
Handler lamborghini = new LamborghiniHandler();
Handler others = new OthersHandler();
// 构建一条责任链(创建单链表)
bentley.setSuccessor(rollsRoyce);
rollsRoyce.setSuccessor(lamborghini);
lamborghini.setSuccessor(others);
// 通过责任链一家家的排查,宾利->劳斯莱斯->兰博基尼,最终找到车型!
String car = "兰博基尼";
Bentley.handlerRequest(car);
}
}
优缺点
责任链模式优点
- 可以将请求的发送者和接受者进行解耦
- 通过改变 handler 的连接顺序来进行次序调动,甚至可以删除
责任链模式缺点
- 不是很容易观察运行时的特点,造成难以找错误
应用场景
使用场景
- 比如窗口系统中,处理鼠标或者键盘的事件
- SpringMVC 的 DispatcherServlet 就是使用了责任链
改进责任链
标准的责任链我们可以看见上面的示例,最明显的特征就是解耦了各个判断的对象,要改哪个判断语句我们可以直接在那个对象中去修改,不用再去关注繁杂的 if else 或者 switch case 了,但是传统的责任链依然有一些麻烦的地方
麻烦点:
- Handler 中的
handlerRequest()
方法往往不是一个,可能有多个 bentley.handlerRequest(car)
这样的写法有不好的地方,万一 Bentley 这个类被我们删掉了怎么办,又要去改这一行代码吗?我们能去设置一个责任链的头结点吗?- 如果
handlerRequest()
方法有多个,同时我们假如有个 head 头结点,那么开始遍历责任链我们应该让 head 调用哪一个handlerRequest()
方法呢?或者专门设置一个start()
?还有如果我们想从责任链中任意一个结点开始遍历呢? - 责任链上各个结点调用
setSuccessor()
来组成完整的链表,但是万一哪个对象我们不需要了,则代码我们需要重新串起来,有些麻烦,有简单的方法不去重新 set,比如说直接删除就行?
基于上面这些考虑我们改进了一下责任链,现在我们再来看一下代码
// 处理请求的责任链结点
public abstract class Handler {
// 后继结点
public Handler successor;
// 责任链
public void start(String car, String status) {
if (status.equals("退货")) {
handlerRequest1(car);
}
else if (status.equals("维修")) {
handlerRequest2(car);
}
else {
System.out.println("没有什么需求请不要打电话骚扰客服!");
}
}
// 退货处理请求 1
public abstract void handlerRequest1(String car);
// 维修处理请求 2
public abstract void handlerRequest2(String car);
// set successor
public Handler setSuccessor(Handler successor) {
this.successor = successor;
}
}
// 头结点
public class HeadHandler extends Handler {
@Override
public void handlerRequest1(String car) {
successor.handlerRequest1(car);
}
@Override
public void handlerRequest2(String car) {
successor.handlerRequest2(car);
}
}
// 宾利 Handler 1
public class BentleyHandler extends Handler {
@Override
public void handlerRequest1(String car) {
if (car.equals("宾利")) {
System.out.println("这里是宾利公司,可以接收宾利汽车退货");
}
else {
successor.handlerRequest1(car);
}
}
@Override
public void handlerRequest2(String car) {
if (car.equals("宾利")) {
System.out.println("这里是宾利公司,可以修理宾利汽车");
}
else {
successor.handlerRequest2(car);
}
}
}
// 劳斯莱斯 Handler 2
public class RollsRoyceHandler extends Handler {
@Override
public void handlerRequest1(String car) {
if (car.equals("劳斯莱斯")) {
System.out.println("这里是劳斯莱斯公司,可以接收劳斯莱斯汽车退货");
}
else {
successor.handlerRequest1(car);
}
}
@Override
public void handlerRequest2(String car) {
if (car.equals("劳斯莱斯")) {
System.out.println("这里是劳斯莱斯公司,可以修理劳斯莱斯汽车");
}
else {
successor.handlerRequest2(car);
}
}
}
// 兰博基尼 Handler 3
public class LamborghiniHandler extends Handler {
@Override
public void handlerRequest1(String car) {
if (car.equals("兰博基尼")) {
System.out.println("这里是兰博基尼公司,可以接收兰博基尼汽车退货");
}
else {
successor.handlerRequest1(car);
}
}
@Override
public void handlerRequest2(String car) {
if (car.equals("兰博基尼")) {
System.out.println("这里是兰博基尼公司,可以修理兰博基尼汽车");
}
else {
successor.handlerRequest2(car);
}
}
}
// 尾结点(终极处理器)
public class TailHandler extends Handler {
@Override
public void handlerRequest1(String car) {
System.out.println("不知道汽车类型,还没有公司能处理此车退货");
}
@Override
public void handlerRequest2(String car) {
System.out.println("不知道汽车类型,还没有公司能处理此车维修");
}
}
// 主函数入口
public class Demo {
public static void main(String[] args) {
// 责任链中的各个对象
Handler head = new HeadHandler();
Handler bentley = new BentleyHandler();
Handler rollsRoyce = new RollsRoyceHandler();
Handler lamborghini = new LamborghiniHandler();
Handler tail = new TailHandler();
// 构建一条完整责任链(创建单链表)
head.setSuccessor(bentley).setSuccessor(rollsRoyce).setSuccessor(lamborghini).setSuccessor(tail);
// 通过责任链一家家的排查,宾利->劳斯莱斯->兰博基尼,最终找到车型!
String car = "兰博基尼";
String status = "维修";
head.start(car, status);
}
}
我们再来看一些这个 demo 优势就显而易见了,它可以通过 head.start()
的方式启动责任链,而不需要通过指定某一个 handlerRequest 方法来启动,并且即使 BentleyHandler 被我们删除,也无需修改head.start()
,还有一个好处,那就是由于 start 方法作为抽象类 handler 的非抽象方法,意味着,我们可以在责任链任意一个结点调用 start 都可以正常的遍历责任链
我们还可以发现setSuccessor()
方法有返回值,这样我们可以连续不断的 setSuccessor,即使中间有某一种 Handler 被我们剔除我们可以直接删除个 setSuccessor 方法,而不是像之前一样还要考虑修改代码时候承上启下的 handler 之间的关系