设计模式 -- 责任链模式

74 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第8天,点击查看活动详情

基本介绍

1)创建一个接收者对象的链,如果一个对象不能处理该请求,怎会传递至下一个对象处理,依次类推

2)属于行为型模式

3)能够使接收者和发送者有效的解耦,对于接收者一端有利于扩展

责任链模式的注意事项和细节

1)客户端只需将请求发送到链上即可,无须关心请求的处理细节和请求的传递。

2)拦截类都实现统一接口

3)优点:(1)降低耦合度 (2)简化了对象 (3)增强给对象指派职责的灵活性 (4)有利于接收者的扩展性

4)缺点:(1)如果一个对象可以由多个接收者处理,具体哪个接收者处理取决于运行时自动确定

类图

1.png

案例代码

package com.example.demo.design.chain;

public abstract class Handler {

    abstract void hanleRequest(String request);

    protected Handler handler;

    public void setSuccessor(Handler handler){
        this.handler = handler;
    }

    public Handler getSuccessor(){
        return handler;
    }

}

package com.example.demo.design.chain;

public class DeptManager extends Handler{

    @Override
    void hanleRequest(String request) {
        if("dept".equals(request)){
            System.out.println("DeptManager 处理请求");
        }else {
            if(getSuccessor() != null){
                getSuccessor().hanleRequest(request);
            }else{
                System.out.println(request + " 没有处理的类型类");
            }
        }
    }
}

package com.example.demo.design.chain;

public class GeneralManager extends Handler{
    @Override
    void hanleRequest(String request) {
        if("general".equals(request)){
            System.out.println("GeneralManager 处理请求");
        }else {
            if(getSuccessor() != null){
                getSuccessor().hanleRequest(request);
            }else{
                System.out.println(request + " 没有处理的类型类");
            }
        }
    }
}

package com.example.demo.design.chain;

public class ProjectManager extends Handler{
    @Override
    void hanleRequest(String request) {
        if("project".equals(request)){
            System.out.println("ProjectManager 处理请求");
        }else {
            if(getSuccessor() != null){
                getSuccessor().hanleRequest(request);
            }else{
                System.out.println(request + " 没有处理的类型类");
            }
        }
    }
}

package com.example.demo.design.chain;


public class Client {

    public static void main(String[] args) {
        //组装责任链
        Handler handler1 = new DeptManager();
        Handler handler2 = new GeneralManager();
        Handler handler3 = new ProjectManager();
        handler1.setSuccessor(handler2);
        handler2.setSuccessor(handler3);

        handler1.hanleRequest("general");
        System.out.println("----------");
        handler1.hanleRequest("dept");
        System.out.println("----------");
        handler1.hanleRequest("project");
        System.out.println("----------");
        handler1.hanleRequest("12312");
    }
}

结果

2.png

责任链模式在Spring MVC 的 DispatcherServlet 类中的应用

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HandlerExecutionChain mappedHandler = null;
        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
        ModelAndView mv = null;
        Exception dispatchException = null;
        
        HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
        if (!mappedHandler.applyPreHandle(processedRequest, response)) {
            return;
        }
        mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
        
        mappedHandler.applyPostHandle(processedRequest, response, mv);
    }

spring mvc执行流程

1、用户发起请求---->DispatcherServlet ,收到请求后不解析,委托给其他解析器进行处理。

2、DispatcherServlet——>HandlerMapping, HandlerMapping 将会把请求映射为HandlerExecutionChain 对象(包含一个Handler 处理器(页面控制器)对象、多个HandlerInterceptor 拦截器)对象,通过这种策略模式,很容易添加新的映射策略;

3、DispatcherServlet——>HandlerAdapter,HandlerAdapter 将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;

4、HandlerAdapter——>处理器功能处理方法的调用,HandlerAdapter 将会根据适配的结果调用真正的处理器的功能处理方法,完成功能处理;并返回一个ModelAndView 对象(包含模型数据、逻辑视图名);

5、ModelAndView的逻辑视图名——> ViewResolver, ViewResolver 将把逻辑视图名解析为具体的View,通过这种策略模式,很容易更换其他视图技术;

6、View——>渲染,View会根据传进来的Model模型数据进行渲染(将数据添加到页面),此处的Model实际是一个Map数据结构,因此很容易支持其他视图技术;

7、返回控制权给DispatcherServlet,由DispatcherServlet返回响应给用户,到此一个流程结束。