Java Code DesignPartten

设计模式-责任链模式

Posted on 2020-09-21,5 min read

定义

  • Avoid coupling the sender of a request to its receiver by giving more than one object an chance to handle the request.Chain the receiving objects and pass the request along the chain until an object handles it.(使多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止)
  • 责任链模式的重点是在"链"上,由一条链去处理相似的请求,在链中决定谁来处理这个请求,并返回相应的结果。

优点

  • 将请求和处理分开:请求者可以不用知道是谁处理的,处理者可以不用知道请求的全貌(例如:J2EE中,可以剥离出无状态Bean由责任链处理),两者解耦他,提高系统灵活性

缺点

  • 性能问题:每个请求都是从链头遍历到链尾,特别是在链比较长的时候,性能是一个非常大的问题
  • 调试不方便:当链表比较长比较多的时候,由于采用了类似递归的方式,调试的时候逻辑可能比较复杂

使用场景

  • 场景:
    • 作为补救模式:如付款功能,后台处理收款。一开始只用处理人民币,但是随着业务的发展,需要处理美金等其他币种。就可以在第一个处理者后面建一条链(责任链)来处理请求,这样不会对原有的业务逻辑产生很大的改变,通过扩展实现类就可以很好的解决这些需求变更的问题
    • 多个if...else或者switch的情况(也可以使用工厂策略模式)

代码

责任链模式

通用类图

责任链模式通用类图

责任链模式还能在下面的代码基础上进行改进。如:对于response对象,由责任链的各个组成部分进行一步步的包装,最后返回一个完整的response对象(参考SpringMVC)

类图

本项目用到的类图

代码

Handler(抽象类

package com.pattern.chainofresponsibili.Handler;


import com.pattern.chainofresponsibili.Request;
import com.pattern.chainofresponsibili.Response;

public abstract class Handler {
    private Handler nextHandler;

    public final Response handleMessage(Request request){
        Response response = null;
        // 判断是否是自己的处理等级
        if(this.getHandlerLevel() == request.getRequestLevel()){
            // 如果是自己的处理等级就处理请求
            response = this.execute(request);
        } else {
            if(this.nextHandler != null){
                // 如果还有下一个处理者
                response = this.nextHandler.handleMessage(request);
            } else {
                // 没有下一个处理者,自行处理
                response = new Response("默认Handler处理");
            }
        }
        return response;
    }

    /**
     * 设置下一个处理者对象
     * @param nextHandler
     */
    public void setNextHandler(Handler nextHandler) {
        this.nextHandler = nextHandler;
    }

    /**
     * 获取每个处理者的处理等级
     * @return
     */
    protected abstract int getHandlerLevel();

    /**
     * 每个处理者对请求进行处理
     * @return
     */
    protected abstract Response execute(Request request);
}

具体Handler(继承自Handler)[减少重复代码,只列出一个Handler实现类,其他类似]

package com.pattern.chainofresponsibili.Handler;

import com.pattern.chainofresponsibili.Request;
import com.pattern.chainofresponsibili.Response;

public class Handler1 extends Handler {
    @Override
    protected int getHandlerLevel() {
        return 1;
    }

    @Override
    protected Response execute(Request request) {
        System.out.println("由Handler1处理了请求");
        return new Response("Handler1执行的请求");
    }
}

Request(普通类

package com.pattern.chainofresponsibili;

/**
 * 模拟一个请求
 */
public class Request {
    private int level;
    public Request(int level){
        this.level = level;
    }
    /**
     * 设置请求等级
     * @param level
     */
    public void setRequestLevel(int level){
        this.level = level;
    }
    /**
     * 返回请求等级
     * @return
     */
    public int getRequestLevel(){
        return this.level;
    }

}

响应类(普通类

package com.pattern.chainofresponsibili;

public class Response {
    private String content;
    public Response(String content){
        this.content = content;
    }

    public String getContent() {
        return content;
    }
}

测试代码

package com.pattern;

import com.pattern.chainofresponsibili.Handler.Handler;
import com.pattern.chainofresponsibili.Handler.Handler1;
import com.pattern.chainofresponsibili.Handler.Handler2;
import com.pattern.chainofresponsibili.Handler.Handler3;
import com.pattern.chainofresponsibili.Request;
import com.pattern.chainofresponsibili.Response;
import org.junit.Test;

public class ChainOfResponsibiliTest {
    @Test
    public void Test(){
        System.out.println("--------模拟一个请求--------");
        Request request = new Request(2);
        System.out.println("--------创建Handler对象--------");
        Handler handler1 = new Handler1();
        Handler handler2 = new Handler2();
        Handler handler3 = new Handler3();
        System.out.println("--------将Handler组成责任链--------");
        handler1.setNextHandler(handler2);
        handler3.setNextHandler(handler3);
        System.out.println("--------测试结果--------");
        Response response = handler1.handleMessage(request);
        System.out.println(response.getContent());
    }
}

结果

责任连模式结果

注意

  • 在责任链模式中一个请求发送到链中后,前一节点消费部分消息,然后由后续节点进行处理,最终可以有处理结果,也可以没有处理结果。
  • handlerMessage(处理请求相关的方法)前要添加final关键字
  • 实际应用中一般会有一个封装类对责任模式进行封装,直接返回链中的第一个处理者,具体链的设置不需要高层模块关系
  • 链中节点数量要控制,避免出现超长链的情况,一般做法是在Handler中设置一个节点数量,并在setNext方法中判断是否已经超过其阀值

下一篇: 设计模式-装饰者模式→

loading...