java设计模式之责任链模式

对着背影说爱祢 提交于 2019-12-10 04:32:37

什么是责任链:

责任链是一种思想,类比现实生活中,在一种需要审批的业务中,用户提交了请求之后就不用管了,至于后续业务中具体是谁审批通过的,用户并不关心也无从得知,只要最终审批通过了就可以。

映射到责任链的这一种设计模式上,解释来说就是:某一个提交的请求对象,在得到最终的结果之前,中间可能要经过多个对象的处理,这些处理请求的对象前后之间存在前置和后继的关系,连接在一起就形成了一个处理链条,对于链条上的每个节点来说,只要能够处理请求,就可以得到请求的结果并返回,否则就把请求继续移交给后续的处理对象,直到最终获取到请求的结果

比如我们熟知的servlet中的filter组件中,就存在责任链模式,还有springsecurity中,大量的责任链模式的使用,下面通过两个简单的案例简要说说责任链模式的使用

案例分享一

需求:用户提交自己的身份证号后,就可以知道自己是否是北京、上海、广州、深圳的户口

1、公共处理者接口

public interface Handler  {

    public abstract void handlerRequest(String number);

    public abstract void setNextHandler(Handler handler);

}

公共的处理者部分如果没有特殊的公共业务,可以直接使用接口即可,否则一般使用抽象类

2、具体的handler,即责任链上的不同的处理器

2.1 BeiJingHandler

public class BeiJingHandler implements Handler {

    private Handler handler;

    private ArrayList<String> numberList;

    public BeiJingHandler() {
        numberList = new ArrayList<>();
        numberList.add("京-0001");
        numberList.add("京-0002");
        numberList.add("京-0003");
    }

    @Override
    public void handlerRequest(String number) {
        if (numberList.contains(number)) {
            System.out.println("该人是北京户口");
        } else {
            System.out.println("该人是不北京户口");
            if(handler != null){
                //将请求传递给下一个处理者
                handler.handlerRequest(number);
            }
        }
    }

    @Override
    public void setNextHandler(Handler handler) {
        this.handler = handler;
    }

}

真实情况下,资源池可以从数据库或者其他的存储数据的地方获取

2.2 ShangHaiHandler

public class ShangHaiHandler implements Handler {

    private Handler handler;

    private ArrayList<String> numberList;

    public ShangHaiHandler() {
        numberList = new ArrayList<String>();
        numberList.add("上海-0001");
        numberList.add("上海-0002");
        numberList.add("上海-0003");
    }

    @Override
    public void handlerRequest(String number) {
        if (numberList.contains(number)) {
            System.out.println("该人是上海户口");
        } else {
            System.out.println("该人不是上海户口");
            if(handler != null){
                //将请求传递给下一个处理者
                handler.handlerRequest(number);
            }
        }
    }

    @Override
    public void setNextHandler(Handler handler) {
        this.handler = handler;
    }

}

2.3 ShangHaiHandler

public class GuangzhouHandler implements Handler {

    private Handler handler;

    private ArrayList<String> numberList;

    public GuangzhouHandler() {
        numberList = new ArrayList<String>();
        numberList.add("广-0001");
        numberList.add("广-0002");
        numberList.add("广-0003");
    }

    @Override
    public void handlerRequest(String number) {
        if (numberList.contains(number)) {
            System.out.println("该人是广州户口");
        } else {
            System.out.println("该人不是广州户口");
            if(handler != null){
                //将请求传递给下一个处理者
                handler.handlerRequest(number);
            }
        }
    }

    @Override
    public void setNextHandler(Handler handler) {
        this.handler = handler;
    }

}

2.4 ShenZhenHandler

public class ShenZhenHandler implements Handler {

    private Handler handler;

    private ArrayList<String> numberList;

    public ShenZhenHandler() {
        numberList = new ArrayList<String>();
        numberList.add("深-0001");
        numberList.add("深-0002");
        numberList.add("深-0003");
    }

    @Override
    public void handlerRequest(String number) {
        if (numberList.contains(number)) {
            System.out.println("该人是深圳户口");
        } else {
            System.out.println("该人不是深圳户口");
            if(handler != null){
                //将请求传递给下一个处理者
                handler.handlerRequest(number);
            }
        }
    }

    @Override
    public void setNextHandler(Handler handler) {
        this.handler = handler;
    }

}

如果后续添加更多的处理器,继续加进去即可,扩展起来很方便

3、测试一下上述的代码

public class AppTest {

    public static void main(String[] args) {

        BeiJingHandler firstHandler = new BeiJingHandler();
        ShangHaiHandler secondHandler = new ShangHaiHandler();
        GuangzhouHandler thirdHandler = new GuangzhouHandler();
        ShenZhenHandler fourthHandler= new ShenZhenHandler();

        firstHandler.setNextHandler(secondHandler);
        secondHandler.setNextHandler(thirdHandler);
        thirdHandler.setNextHandler(fourthHandler);

        firstHandler.handlerRequest("深-0002");

    }

}

在这里插入图片描述

通过这样一个简单的需求,用户提交了一个需求后,系统会根据各自处理器的功能,最终获取到自己的结果

案例分享二

需求说明:在一个需要审批的业务中,不同的角色具有不同的审批权限,比如同学提交的申请表到班长那里,班长提交的申请表再转到班主任,班主任的请求转到院长那里,同学无法审批班长的请求,班长也无法审批班主任的请求

1、抽象请求

由于需要在后续业务中通过获取请求对象的级别,即一个公共的业务,这里采用了抽象类

public abstract class AbstractRequest {

    String content = "";

    public AbstractRequest(){
        this.content = content;
    }

    public String getContent() {
        return content;
    }

    //获取处理请求的级别
    public abstract int getRequestLever();

}

2、抽象责任处理器

public abstract class AbstractHandler {

    // 责任链的下一个节点,即处理者
    private AbstractHandler nextHandler = null;

    // 捕获具体请求并进行处理,或是将请求传递到责任链的下一级别
    public final void handleRequest(AbstractRequest request) {
        // 若该请求与当前处理者的级别相对应,则由自己进行处理
        if (this.getHandlerLever() == request.getRequestLever()) {
            this.handlered(request);
        } else {
            // 当前处理者不能胜任,则传递至职责链的下一节点
            if (nextHandler != null) {
                System.out.println("当前处理者 0" + this.getHandlerLever() + "不足以处理请求 0" + request.getRequestLever());
                // 这里使用了递归调用
                this.nextHandler.handleRequest(request);
            } else {
                System.out.println("职责链上的所有处理者都不能胜任该请求...");
            }
        }
    }

    // 设置责任链中的下一个处理者
    public void setNextHandler(AbstractHandler nextHandler) {
        this.nextHandler = nextHandler;
    }

    // 获取当前处理者的级别
    public int getHandlerLever() {
        return 0;
    }

    // 定义链中每个处理者具体的处理方式
    protected abstract void handlered(AbstractRequest request);

}

3、获取不同请求的请求级别

这里假如有3个级别的请求处理器:

3.1 请求处理器1

public class Request01 extends AbstractRequest {

    public Request01(String content) {
        this.content = super.getContent();
    }

    @Override
    public int getRequestLever() {
        return 1;
    }
}

public class Handler01 extends AbstractHandler{

    @Override
    public int getHandlerLever() {
        return 1;
    }

    @Override
    protected void handlered(AbstractRequest request) {
        System.out.println("处理者-01 同学 " + request.getContent() + "\n");
    }
}

3.2 请求处理器2

public class Request02 extends AbstractRequest {

    public Request02(String content) {
        this.content = super.getContent();
    }

    @Override
    public int getRequestLever() {
        return 2;
    }
}
public class Handler02 extends AbstractHandler {

    @Override
    public int getHandlerLever() {
        return 2;
    }

    @Override
    protected void handlered(AbstractRequest request) {
        System.out.println("处理者-02 班长 " + request.getContent() + "\n");
    }
}

3.3 请求处理器3

public class Request03 extends AbstractRequest {

    public Request03(String content) {
        this.content = super.getContent();
    }

    @Override
    public int getRequestLever() {
        return 3;
    }
}
public class Handler03 extends AbstractHandler {

    @Override
    public int getHandlerLever() {
        return 3;
    }

    @Override
    protected void handlered(AbstractRequest request) {
        System.out.println("处理者-03 班主任 " + request.getContent() + "\n");
    }
}

4、测试类

public class TestMain {

    /*public static void main(String[] args) {

        // 创建请求并提交到指责链中进行处理
        AbstractRequest request01 = new Request01("同学请求");
        AbstractRequest request02 = new Request02("班长请求");
        AbstractRequest request03 = new Request03("主任请求");

        // 创建指责链的所有节点
        AbstractHandler handler01 = new Handler01();
        AbstractHandler handler02 = new Handler02();
        AbstractHandler handler03 = new Handler03();

        // 进行链的组装,即头尾相连,一层套一层
        handler01.setNextHandler(handler02);
        handler02.setNextHandler(handler03);

        // 每次提交都是从链头开始遍历
        //handler01.handleRequest(request01);
        handler01.handleRequest(request02);
        //handler01.handleRequest(request03);

    }*/


    public static void handleRequest(String requestName) {
        // 创建指责链的所有节点
        AbstractHandler handler01 = new Handler01();
        AbstractHandler handler02 = new Handler02();
        AbstractHandler handler03 = new Handler03();

        // 进行链的组装,即头尾相连,一层套一层
        handler01.setNextHandler(handler02);
        handler02.setNextHandler(handler03);

        if("同学请求".equals(requestName)){
            AbstractRequest request01 = new Request01("同学请求");
            handler01.handleRequest(request01);
        }

        if("班长请求".equals(requestName)){
            AbstractRequest request02 = new Request02("班长请求");
            handler01.handleRequest(request02);
        }

        if("主任请求".equals(requestName)){
            AbstractRequest request03 = new Request03("主任请求");
            handler01.handleRequest(request03);
        }

    }

    public static void main(String[] args) {
        String requestName = "班长请求";
        handleRequest(requestName);
    }

}

处理请求的时候一般是从第一个处理器开始,责任链中的处理器一旦确定,就需要提前将他们的前后置关系设定好,之后不同的请求过来了只需要从第一个handler开始

在这里插入图片描述

在真实的业务中,责任链上的各个处理器,是根据需求提前设计好的,每个处理器具体要处理哪一部分的功能,比如处理器1校验参数合法性,处理器2校验token,处理器3校验某个参数是否存在等,都是动态进行的,责任链模式也正是具备这种热插拔、动态扩展的特性使得它在一些特定的场合中很有效

本篇简单分享了责任链模式的使用,更深入的比如像springsecurity中是如何使用这种模式的,有兴趣的同学可以继续深入研究,最后感谢观看!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!