23种设计模式(13) - 责任链模式
1、定义
使多个对象都有机会处理请求,从而避免请求的发送者和接受者质检的耦合关系。将这个接收对象连成一条链,并沿着这条链传递请求,直到有一个对象处理他为止。
2、UML 图
3、组成
- 抽象处理器(Handler):主要包含了处理方法
handlerRequest
和转交对象nextHandler
,他的思想是,如果自己能处理则自己处理,否则交给转交对象处理 - 处理器实现类(FirstHandler):处理器的实现类,每个实现类自己定义处理逻辑
4、代码
先来看一个反面例子代码,使用大量的if
判断来选择执行逻辑:
public Response handleRequest(Request request) {
Level level = request.getLevel();
if (1 == level) {
Handler1.handleRequest(request);
} else if (2 == level) {
Handler2.handleRequest(request);
} else if (3 == level) {
Handler3.handleRequest(request);
}
throw new RuntimeException("无法处理 ......")
}
这样的代码有以下缺点:
- 代码臃肿:如果判断条件不是简单的
1==level
,而是更复杂的计算,那代码可读性会很不好; - 耦合性高:如果新加一种情况,需要新加
if else
语句,改变了原来代码,违反了 封闭-开放 原则。
以下是使用责任链模式的代码:
// 抽象处理类
public abstract class Handler {
// 下一个处理器处理
protected Handler nextHandler;
void setNextHandler(Handler nextHandler){
this.nextHandler = nextHandler;
}
final Response handleRequest(Request request){
// 如果自己能处理,则自己处理
if(request.getLevel() == getHandlerLevel()){
return this.doHandler(request);
}
System.out.println("本处理器:"+getHandlerLevel()+" 无法处理,开始转交 ......");
if(null != this.nextHandler){
// 如果不能处理,转交给下一个处理器处理
return this.nextHandler.handleRequest(request);
} else {
System.out.println("无合适的处理器,处理失败 ......");
}
return null;
}
// 自己处理的任务标识
abstract Level getHandlerLevel();
// 实际处理逻辑,子类自己定义
abstract Response doHandler(Request request);
}
// 任务标识,用于区分用哪个处理器处理
public enum Level {
FIRST_LEVEL,
SECOND_LEVEL,
THIRD_LEVEL;
}
//请求类
public class Request {
private Level level;
public Request(Level level){
this.level = level;
}
public Level getLevel() {
return level;
}
}
// 处理结果类
public class Response {
}
// 第一个处理器
public class FirstConcreteHandler extends Handler {
@Override
Level getHandlerLevel() {
return Level.FIRST_LEVEL;
}
@Override
Response doHandler(Request request) {
System.out.println("本处理器:"+getHandlerLevel()+" 开始处理 .....");
return null;
}
}
// 第二个处理器
public class SecondConcreteHandler extends Handler {
@Override
Level getHandlerLevel() {
return Level.SECOND_LEVEL;
}
@Override
Response doHandler(Request request) {
System.out.println("本处理器:"+getHandlerLevel()+" 开始处理 .....");
return null;
}
}
// 第三个处理器
public class ThirdConcreteHandler extends Handler {
@Override
Level getHandlerLevel() {
return Level.THIRD_LEVEL;
}
@Override
Response doHandler(Request request) {
System.out.println("本处理器:"+getHandlerLevel()+" 开始处理 .....");
return null;
}
}
//调用者
public class Main {
public static void main(String[] args) {
Handler firstHandler = new FirstConcreteHandler();
Handler secondHandler = new SecondConcreteHandler();
Handler thirdHandler = new ThirdConcreteHandler();
firstHandler.setNextHandler(secondHandler);
secondHandler.setNextHandler(thirdHandler);
// 需要第三个处理类处理
Request request = new Request(Level.THIRD_LEVEL);
firstHandler.handleRequest(request);
}
}
输出结果如下:
本处理器:FIRST_LEVEL 无法处理,开始转交 ......
本处理器:SECOND_LEVEL 无法处理,开始转交 ......
本处理器:THIRD_LEVEL 开始处理 .....
5、优缺点
- 只需要在代码中将各中情况链式创起来,使用者只需要知道一个入口,而不用管具体的执行逻辑;
- 责任链模式是变相版的
if else
语句,如果链过长,会过量消耗性能; - 责任链的链不能出现循引用的情况,否则会出现死循环
6、适用场景
责任链模式其实就是一个灵活版的if…else…
语句,只不过它把判断条件放在每个链的节点类中。如觉得代码中if…else…
语句使得程序可读性不好,可以考虑责任链模式。