前言
本文来谈谈责任链模式。
正文
概念
责任链模式属于行为型模式。正如名字所说一样,对象是一个链式的结构,当请求到达对象时,如果第一个对象不能处理这个请求,则将请求传递给下一个对象,以此类推。
责任链可以是直线型,也可以是环形,又或者是树形。那这种设计模式简化了请求传递的复杂度,请求只要传递给责任链上,并且无需关心如何处理请求,所以责任链模式将请求者与接受者解耦了。
那我们常见的场景有:
- js中的事件冒泡,事件会依次向上传递。
- jvm中的类加载机制也是责任链模式,但会一直指派到最顶级的类加载。
实现
责任链模式中有两个角色:
- 抽象处理者(Handler):抽象对象或者接口。定义一个处理请求的接口。
- 具体处理者(ConcreteHandler):具体的请求处理者,接收请求后选择是否处理请求,如不处理,则传递给下一位。
我们先用简单的例子:
首先创建handler:
1 2 3 4 5 6 7 8 9 10 11 12 13
| public abstract class Handler { protected Handler nextHandler;
public Handler getNextHandler() { return nextHandler; }
public void setNextHandler(Handler nextHandler) { this.nextHandler = nextHandler; } public abstract void handlerRequest(String name); }
|
随后我们创建具体的处理者:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| public class ConcreteHandlerA extends Handler{ @Override public void handlerRequest(String name) { if (name.equals("A")){ System.out.println("handler A 处理请求"); return; }
if (getNextHandler() != null){ System.out.println("handler A 无法处理请求,转交给下一个handler"); getNextHandler().handlerRequest(name); return; }
System.out.println("所有handler都无法处理请求"); } } public class ConcreteHandlerB extends Handler{ @Override public void handlerRequest(String name) { if (name.equals("B")){ System.out.println("handler B 处理请求"); return; }
if (getNextHandler() != null){ System.out.println("handler B 无法处理请求,转交给下一个handler"); getNextHandler().handlerRequest(name); return; }
System.out.println("所有handler都无法处理请求"); } }
|
这里我们重写handlerRequest方法,当这个具体处理者可以处理请求时,直接处理请求,不能处理时,我们传给责任链中下一个处理者,如果没有下一个处理者就退出。
最后是客户端,其中客户端中我们需要显式地构建责任链。我们编写客户端试试:
1 2 3 4 5 6 7 8 9 10
| public class Client { public static void main(String[] args) { Handler handlerA = new ConcreteHandlerA(); Handler handlerB = new ConcreteHandlerB();
handlerA.setNextHandler(handlerB);
handlerA.handlerRequest("C"); } }
|
这里我们将handlerA 的下一个责任链对象设置为handlerB,这样所有的handler形成了一个链表,我们只需将所有请求发送给handlerA,就无需关心请求是如何进行处理是谁处理的。
常见需求场景
所以责任链模式适用于一级一级传递的需求当中。比如日志管理,那我们常见的日志级别就是一级一级的,有debug,info,warning,error等等的级别,当日志级别设为较低一级时,它以上的日志都会打印。
又比如权限的管理,比如操作的级别有很多级,对服务器越危险的操作就必须有更高权限的人来确认操作,那根据操作的级别,把请求传递给责任链,权限不足就交给上一级,直到这个操作进行确认。
这里感兴趣的同学可以动手写写简单的实现代码。
优缺点
那责任链模式能一定程序上降低请求的发送者与处理者之间的耦合,不用关心请求发送给哪个处理者。其次对于指派处理者较为灵活,可以改变链中的顺序和成员,动态增加和删除。
那缺点在于不能保证请求一定被接收,其次就是环的解决,如果处理不当,有可能导致循环调用。