职责链模式,是11种行为型模式之一。在 GoF 的《设计模式》一书中,它是这样定义的:Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it. 翻译成中文就是:通过给多个对象一个处理请求的机会,避免将请求的发送方与接收方耦合。链接接收对象并沿着链传递请求,直到对象处理它为止。 通俗的讲就是把请求发送给多个职责不同的对象,这些对象依次根据职责处理请求,直到请求被响应为此。而这些对象通常被称呼为处理器(Handler)、过滤器(Filter)、拦截器(Interceptor)。职责链模式对于普通开发人员来说是最经常跟框架打交道的模式之一,另一个模式个人认为是观察者模式(监听器)。开发者通过自定义过滤器、监听器实现框架的扩展。
所谓职责链,就是责任对象根据职责按先后顺序执行,看起来像串在一条链上,责任对象处理请求后把请求传递给下一个责任对象,责任对象可以根据情况选择是否把请求传给下一个责任对象。
职责链模式有两种实现方式,一种是通过链表来保存对象,另一种是通过数组(集合)保存对象。根据保存方式不同,实现上有些变化。下面通过代码来看两种方式如何实现。
-
链表方式:
//请求接口
public interface Request {
}
//职责链接口
public interface Chain {
public void handle(Request request);
}
//处理器接口
public abstract class Handler {
private Handler next;
public void setNext(Handler nextHandler){
this.next = nextHandler;
}
public Handler getNext(){
return this.next;
}
public abstract void handle(Request request, Chain chain);
}
public class AHandler extends Handler{
@Override
public void handle(Request request, Chain chain) {
//依据职责进行处理
//根据处理结果,决定是否把请求传给下一个处理器
chain.handle(request);
//后续职责进行处理
}
}
public class BHandler extends Handler{
@Override
public void handle(Request request, Chain chain) {
//依据职责进行处理
//根据处理结果,决定是否把请求传给下一个处理器
chain.handle(request);
//后续职责进行处理
}
}
/**
* 职责链对象
* 把处理器串成链,并执行处理器
*/
public class HandlerChain {
private Handler head = null;
private Handler tail = null;
private Handler next = null;
public void addHandler(Handler handler){
handler.setNextHandle(null);
if (this.head == null) {
head = handler;
tail = handler;
next = head;
return;
}
tail.setNext(handler);
tail = handler;
}
public void handle(Request request) {
if (next != null) {
Handler current = next;
next = handler.getNext();
current.handle(request, this);
}
}
}
public class Client {
public static void main(String[] args) {
HandlerChain chain = new HandlerChain();
chain.addHandler(new AHandler());
chain.addHandler(new BHandler());
chain.handle(new Request());
}
}
-
数组(集合)方式:
//请求接口
public interface Request {
}
//职责链接口
public interface Chain {
public void handle(Request request);
}
//处理器接口
public interface Handler {
public void handle(Request request, Chain chain);
}
public class AHandler implements Handler{
@Override
public void handle(Request request, Chain chain) {
//依据职责进行处理
//根据处理结果,决定是否把请求传给下一个处理器
chain.handle(request);
//后续职责进行处理
}
}
public class BHandler implements Handler{
@Override
public void handle(Request request, Chain chain) {
//依据职责进行处理
//根据处理结果,决定是否把请求传给下一个处理器
chain.handle(request);
//后续职责进行处理
}
}
/**
* 职责链对象
* 把处理器串成链,并执行处理器
*/
public class HandlerChain implements Chain {
private List<Handler> handlers = new AarryList<>();
private int pos = 0;
public void addHandler(Handler handler){
handlers.add(handler)
}
public void handle(Request request) {
if (this.pos < handlers.size())
handlers[this.pos++].handle(request, this);
}
}
public class Client {
public static void main(String[] args) {
HandlerChain chain = new HandlerChain();
chain.addHandler(new AHandler());
chain.addHandler(new BHandler());
chain.handle(new Request());
}
}
链表方式应用如nettey的ChannelPipeline:
public class DefaultChannelPipeline implements ChannelPipeline {
final AbstractChannelHandlerContext head;
final AbstractChannelHandlerContext tail;
private final Channel channel;
//省略其他代码
public final ChannelPipeline addLast(ChannelHandler handler) {
return this.addLast((String)null, (ChannelHandler)handler);
}
public final ChannelPipeline addLast(ChannelHandler... handlers) {
return this.addLast((EventExecutorGroup)null, (ChannelHandler[])handlers);
}
public final ChannelPipeline addLast(EventExecutorGroup executor, ChannelHandler... handlers) {
if (handlers == null) {
throw new NullPointerException("handlers");
} else {
ChannelHandler[] var3 = handlers;
int var4 = handlers.length;
for(int var5 = 0; var5 < var4; ++var5) {
ChannelHandler h = var3[var5];
if (h == null) {
break;
}
this.addLast(executor, (String)null, h);
}
return this;
}
}
private void addLast0(AbstractChannelHandlerContext newCtx) {
AbstractChannelHandlerContext prev = this.tail.prev;
newCtx.prev = prev;
newCtx.next = this.tail;
prev.next = newCtx;
this.tail.prev = newCtx;
}
//省略 addFirst 、 addBefore 、 addAfter
public final ChannelPipeline fireChannelRegistered() {
A
bstractChannelHandlerContext.invokeChannelRegistered(this.head);
return this;
}
public final ChannelPipeline fireChannelUnregistered() {
AbstractChannelHandlerContext.invokeChannelUnregistered(this.head);
return this;
}
}
//省略其他代码
}
数组(集合)方式应用如java filter的tomcat实现ApplicationFilterChain、spring interceptor的HandlerExecutionChain。
以ApplicationFilterChain举例:
public final class ApplicationFilterChain implements FilterChain {
private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];
private int pos = 0;
private int n = 0;
private Servlet servlet = null;
public ApplicationFilterChain() {
}
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
if (Globals.IS_SECURITY_ENABLED) {
final ServletRequest req = request;
final ServletResponse res = response;
//省略其他代码
AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
public Void run() throws ServletException, IOException {
ApplicationFilterChain.this.internalDoFilter(req, res);
return null;
}
});
//省略其他代码
} else {
this.internalDoFilter(request, response);
}
}
private void internalDoFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
//在所有过滤器都调用之前,依次调用过滤器
if (this.pos < this.n) {
ApplicationFilterConfig filterConfig = this.filters[this.pos++];
//省略其他代码
Filter filter = filterConfig.getFilter();
//省略其他代码
//调用过滤器
if (Globals.IS_SECURITY_ENABLED) {
Principal principal = ((HttpServletRequest)request).getUserPrincipal();
Object[] args = new Object[]{request, response, this};
SecurityUtil.doAsPrivilege("doFilter", filter, classType, args, principal);
} else {
filter.doFilter(request, response, this);
}
//省略其他代码
} else {
//省略其他代码
//所有过滤器执行结束后,以下执行servlet
if (request instanceof HttpServletRequest && response instanceof HttpServletResponse && Globals.IS_SECURITY_ENABLED) {
Principal principal = ((HttpServletRequest)request).getUserPrincipal();
Object[] args = new Object[]{request, response};
SecurityUtil.doAsPrivilege("service", this.servlet, classTypeUsedInService, args, principal);
} else {
this.servlet.service(request, response);
}
//省略其他代码
}
}
void addFilter(ApplicationFilterConfig filterConfig) {
ApplicationFilterConfig[] newFilters = this.filters;
int len$ = newFilters.length;
//检查是否已经添加
for(int i$ = 0; i$ < len$; ++i$) {
ApplicationFilterConfig filter = newFilters[i$];
if (filter == filterConfig) {
return;
}
}
//数组不够大了,就扩容
if (this.n == this.filters.length) {
newFilters = new ApplicationFilterConfig[this.n + 10];
System.arraycopy(this.filters, 0, newFilters, 0, this.n);
this.filters = newFilters;
}
this.filters[this.n++] = filterConfig;
}
}
现在知道职责链模式是怎样的一种模式,但为什么要用职责链模式,职责链模式有什么作用?我们通过模拟java的Servlet来实现一下。
没用职责链式:
//请求接口
public interface Request {
}
//响应接口
public interface Response {
}
//处理器接口
public interface Handler {
public abstract void handle(Request request, Chain chain);
}
public class AHandler implements Handler{
private Handler nextHandler;
AHandler(Handler nextHandler){
this.nextHandler = nextHandler;
)
@Override
public void handle(Request request,Response response) {
//依据职责进行处理
//根据处理结果,决定是否把请求传给下一个处理器
this.nextHandler.handle(request,response);
//后续职责进行处理
}
}
public class BHandler implements Handler{
private Handler nextHandler;
BHandler(Handler nextHandler){
this.nextHandler = nextHandler;
)
@Override
public void handle(Request request,Response response) {
//依据职责进行处理
//根据处理结果,决定是否把请求传给下一个处理器
this.nextHandler.handle(request);
//后续职责进行处理
}
}
//servlet 可以当作每个系统的API
public abstract class Servlet {
public void service(Request request,Response response){
//调用处理器
AHandler b = new AHandler();
AHandler a = new AHandler(b);
a.handle(request,response);
}
}
/**
*/
public class AServlet extends Servlet {
public void service(Request request,Response response){
super.service(request,response);
//处理请求
//响应请求
}
}
/**
*/
public class BServlet implements Servlet {
public void service(Request request,Response response){
super.service(request,response);
//处理请求
//响应请求
}
}
public class Client {
public static void main(String[] args) {
AServlet a = new AServlet();
a.service(new Request(),new Response ());
}
}
可以看到没有用到职责链模式,Client会直接调用Servlet。例子中调用了A和B处理器,当需要添加C处理器时,就得修改Servlet。而每个servlet都与处理器形成依赖关系。当处理器出现异常等同所有Servlet异常,是不应该出现的。由于处理器处理不是Servlet的职责,让Servlet依赖处理器,违反了单一职责原则。另外super.service()的调用主动权在Servlet的实现类,容易忘记或有条件调用,出现不可测的问题。
职责链模式遵循的设计原则和思想:
- 多用组合少用继承的思想:用职责链类组合处理器和Servlet,解耦处理器与Servlet;
- 单一职责原则:职责链类负责调用处理器和Servlet,让Servlet职责更加单一;
- 开闭原则:添加处理器,只需要在职责链类中添加一行,不影响其他原有代码;