基本概念
- 定义:使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,知道有对象处理它为止。
- COR(责任链)模式的角色分工:
- Handler:抽象处理者,定义一个处理请求的接口
- Concrete Handler: 具体处理者,处理请求的具体类,或者传给”下家”。
- Requester:发出请求等待处理的类,它无需关注到底是哪个具体的Handler处理它的请求
- COR的处理问题的场景:
- 一个request在多个handler中选择合适的进行处理
- 传统的通过switch或者if-else进行判断,然后执行
- 职责界定不清晰,不满足单一职责准则
- 代码臃肿,可读性差
- 耦合过重,Request调用具体实现,不便与Handler地拓展,丧失了面向接口编程的在实现层面低耦合的优点
- 没有对选择逻辑进行封装,具体实现被暴露,容易出现异常
- COR(责任链)模式,则是提供了抽象Handler接口
- 每个具体的Handler的实现不与Requester耦合,只需要定义自己的处理级别,然后对于一个请求要么承担责任,做出回应;要么把请求转发到后续环节
- Requester也无需知道具体为我提供服务的Handler的情况,只需提交请求即可
- COR(责任链)模式的优缺点:
- 优点:
- 父类实现了请求传递的功能,子类实现请求的处理,符合单一职责原则,各个类实现一个动作或逻辑,也就是只有一个原因引起类的变化,子类的实现非常简单,责任链的建立也是非常灵活的。
- 责任链模式屏蔽了请求的处理过程,你发起的一个请求到底是谁处理的,这个你不用关心,只要把请求抛给责任链,就会得到结果,无需关心具体由谁处理,这时责任链的核心
- 缺点:
- 主要的是性能问题,责任链较长时,性能会下降得很快
- 不方便调试
- 优点:
例讲COR(责任链)模式
在平时的生活中,小伙伴们一起共事,经常在遇到问题时会甩锅,但是最终总是有人要背锅的,当然就是这件事的负责人了(虽然可能有时候是无辜的),但是锅是要背的,23333,那么我们来看看甩锅这段程序如何用责任链模式实现:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* Created by liulin on 16-4-26.
*/
class ErrorRequester{
//标记请求的类型
private String duty;
public String getDuty() {
return duty;
}
public void setDuty(String duty) {
this.duty = duty;
}
}
abstract class Handler{
//记录当前责任链的下一个元素
private Handler nextHandler;
//标记当前子类的类型
private String duty;
public static final String DBA="SQL and the database";
public static final String FRONT="HTML and CSS";
public static final String BGD="Java and XML";
//方便子类设置自己的类型(子类通过无参数的构造器隐藏该实现)
public Handler ( String duty ){
this.duty = duty;
}
//责任链的职责传递逻辑的实现,不支持子类的覆盖
public final void handleMessage ( ErrorRequester requester ){
if( requester.getDuty().equals(duty)){
response( requester);
}else{
if( nextHandler != null ){
nextHandler.handleMessage( requester );
}else{
System.out.println("The Error is due to others!!!");
}
}
}
public final void setNextHandler( Handler handler ){
nextHandler = handler;
}
//TODO 匹配到合适的类型时的,回应请求的函数
protected abstract void response( ErrorRequester requester );
}
class DBAHandler extends Handler{
//设置当前子类的处理器类型
public DBAHandler() {
super( Handler.DBA);
}
//如果当前类型匹配上,那么进行响应
@Override
protected void response(ErrorRequester requester) {
System.out.println( "What horrible "+ requester.getDuty() + " is!!!!");
}
}
class BGDHandler extends Handler{
public BGDHandler() {
super(Handler.BGD);
}
@Override
protected void response(ErrorRequester requester) {
System.out.println("What horrible " + requester.getDuty() + " is!!!");
}
}
class FRONTHandler extends Handler{
public FRONTHandler() {
super(Handler.FRONT);
}
@Override
protected void response(ErrorRequester requester) {
System.out.println("What horrible " + requester.getDuty() + " is!!!");
}
}
public class CORTest {
public static void main ( String [] args ){
//构造词典
HashMap<Integer,String> dic = new HashMap();
dic.put ( 0 , Handler.DBA );
dic.put ( 1 , Handler.BGD );
dic.put ( 2 , Handler.FRONT);
int times = 0;
//建立责任链
Handler dba = new DBAHandler();
Handler bgd = new BGDHandler();
Handler front = new FRONTHandler();
dba.setNextHandler( bgd );
bgd.setNextHandler( front );
//生成随机的请求,并且响应
while ( times++ != 10 ){
ErrorRequester requester = new ErrorRequester();
requester.setDuty( dic.get((int)(Math.random()*100)%3) );
dba.handleMessage( requester );
}
}
}
结果如下:
Tomcat中对于COR的应用
Tomcat的容器设置就是责任链模式,从Engine到Host再到Context一知道Wraper都通过一个链传递请求。
- 其中的角色分工:
- Container:抽象Handler
- StandardEngine….等: 具体Handler
- 与标准的责任链相比引入了新的角色:
- PipeLine:作为请求传递的管道
- Value:在管道上对请求加工
- 为了防止请求流不到下一个容器,每一段PipeLine总会有一个节点保证它一定能够流到下一个容器,所以每个容器都有一个StandardXXXValue