23种设计模式(13) - 责任链模式

1、定义

使多个对象都有机会处理请求,从而避免请求的发送者和接受者质检的耦合关系。将这个接收对象连成一条链,并沿着这条链传递请求,直到有一个对象处理他为止。

2、UML 图

8fHV6x.png

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…语句使得程序可读性不好,可以考虑责任链模式。

posted @ 2020-03-24 00:56  MoonGeek  阅读(347)  评论(0编辑  收藏  举报