简介
责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。
特点
- 有多个对象共同对一个任务进行处理。
- 这些对象使用链式存储结构,形成一个链,每个对象知道自己的下一个对象。
- 一个对象对任务进行处理,可以添加一些操作后将对象传递个下一个任务。也可以在此对象上结束任务的处理,并结束任务。
- 客户端负责组装链式结构,但是客户端不需要关心最终是谁来处理了任务。
分析
在责任链模式中,存在着这么几个角色:
- Handler-处理者
handler定义了处理请求的接口,同时指定了下一个处理者。如果当前handler无法处理请求,就转给下一个处理者。
- ConcreteHandler-具体的处理者
具体的处理者是处理请求的具体的角色。
- client
请求者角色就是向第一个具体的handler发送请求的角色,并连接好责任链
举例
1、创建处理器接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| package chain.patten;
public abstract class Handler { public Handler handler; public void setSuccessor(Handler handler){ this.handler=handler; } public abstract void request(int request); }
|
2、创建处理器对象1
1 2 3 4 5 6 7 8 9 10 11 12 13
| package chain.patten;
public class ConcreteHandler1 extends Handler { @Override public void request(int request) { if(request<10){ System.out.println("我是handler1,我处理了请求:"+request); }else { this.handler.request(request); } } }
|
3、创建处理器对象2
1 2 3 4 5 6 7 8 9 10 11 12 13
| package chain.patten;
public class ConcreteHandler2 extends Handler { @Override public void request(int request) { if(request>10){ System.out.println("我是handler2,我处理了请求:"+request); }else { System.out.println("请求"+request+"没人能处理"); } } }
|
4、创建客户端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package chain.patten;
public class Client { public static void main(String[] args) { Handler handler1=new ConcreteHandler1(); Handler handler2=new ConcreteHandler2(); handler1.setSuccessor(handler2); int[] requests={4,10,59,2,16}; for(int request:requests){ handler1.request(request); } } }
|
优点
1、降低耦合度。它将请求的发送者和接收者解耦。
2、简化了对象。使得对象不需要知道链的结构。
3、增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。
4、增加新的请求处理类很方便。
缺点
1、不能保证请求一定被接收。
2、系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。
3、可能不容易观察运行时的特征,有碍于除错。
具体应用
- servlet中的filter
- dubbo中的filter
servlet中的Filter
servlet中分别定义了一个 Filter和FilterChain的接口,核心代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public final class ApplicationFilterChain implements FilterChain { private int pos = 0; private int n; private ApplicationFilterConfig[] filters; private Servlet servlet @Override public void doFilter(ServletRequest request, ServletResponse response) { if (pos < n) { ApplicationFilterConfig filterConfig = filters[pos++]; Filter filter = filterConfig.getFilter(); filter.doFilter(request, response, this); } else { servlet.service(request, response); } } }
|
Dubbo中的Filter
Dubbo在创建Filter的时候是另外一个方法,通过把Filter封装成 Invoker的匿名类,通过链表这样的数据结构来完成责任链,核心代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| private static <T> Invoker<T> buildInvokerChain(final Invoker<T> invoker, String key, String group) { Invoker<T> last = invoker; List<Filter> filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group); if (filters.size() > 0) { for (int i = filters.size() - 1; i >= 0; i --) { final Filter filter = filters.get(i); final Invoker<T> next = last; last = new Invoker<T>() { ... public Result invoke(Invocation invocation) throws RpcException { return filter.invoke(next, invocation); } ... }; } } return last; }
|
参考资料