Este artículo lo lleva a comprender el modelo de cadena de responsabilidad del patrón de diseño | Equipo técnico de JD Cloud

1. Introducción

emm, revisé las notas de estudio cuando me uní al trabajo por primera vez, y descubrí que había estudiado y ordenado el modelo de cadena de responsabilidad en el patrón de diseño cuando estaba familiarizado con el código comercial . patrones de diseño comúnmente utilizados.Sin combinar ejemplos y código fuente para explorarlo en profundidad, aproveche la oportunidad de estar familiarizado con el código para estudiar sistemáticamente y organizar los documentos de la siguiente manera.

2. ¿Qué es el patrón de la Cadena de Responsabilidad?

Como dice el refrán, no hay regla sin reglas. Necesitamos seguir los procedimientos prescritos para muchas cosas, ya sea en el trabajo o en la vida. Dichos procedimientos a menudo se entrelazan. Una vez que se completa el anterior, se transferirá al siguiente. paso para la ejecución. Por ejemplo, cuando cocinamos, siempre compramos verduras, lavamos verduras, cortamos verduras, freímos verduras y las ponemos en el plato. En este proceso, solo después de completar el paso anterior podemos comenzar el siguiente paso y finalmente tener una lista. plato; otro ejemplo es cuando se nomina para la promoción, primero tenemos que hacer un informe informativo para el informe final, y luego el equipo de revisión calificará. Después de que el equipo de revisión pase la evaluación, se transferirá al líder del equipo del proyecto para su aprobación. El líder del equipo del proyecto decidirá si promocionar de acuerdo con el informe informativo y la puntuación del equipo de revisión.Después de que el líder del equipo del proyecto esté de acuerdo.Finalmente, pasa al líder del departamento para su aprobación y da el resultado final. Un proceso paso a paso como este se puede lograr a través del modelo de cadena de responsabilidad.

  • Introducción: el modelo de cadena de responsabilidad, como su nombre indica, consiste en ejecutar los pasos de diferentes responsabilidades en serie, y el siguiente paso solo se puede ejecutar después de completar la ejecución de un paso. Como se puede ver en el nombre, el patrón de Cadena de responsabilidad generalmente se implementa mediante una lista enlazada. Por lo tanto, cuando se inicia una solicitud para realizar una tarea, se transmite desde el primer paso en la cadena de responsabilidad hasta que se completa el último paso. En el modo de cadena de responsabilidad, el cliente solo necesita ejecutar la solicitud para iniciar el proceso una vez y ya no necesita participar en la ejecución del proceso. El proceso en la cadena de responsabilidad puede ejecutarse continuamente. Al cliente tampoco le importa el detalles del proceso de ejecución Para lograr el desacoplamiento del proceso.
  • Estructura del modo : Las funciones principales del modo de cadena de responsabilidad son las siguientes:

◦Procesador abstracto (Handler) : la interfaz abstracta del procesador define el método de procesamiento de solicitudes y el procesador que realiza el siguiente paso.

◦Concrete handler (ConcreteHandler) : la implementación específica de la solicitud de ejecución, primero ejecuta la lógica de procesamiento de acuerdo con la solicitud y luego pasa la solicitud al siguiente procesador para su ejecución.

◦ Persona que llama : la persona que llama crea un procesador y entrega la solicitud al procesador para que la procese .

  • Código relevante:
// 抽象处理器
public abstract class Handler {
    private Handler next;

    public Handler getNext() {
        return next;
    }

    public void setNext(Handler next) {
        this.next = next;
    }
    public abstract void handle(Object request);
}

// 具体处理器 1
public class ConcreteHandler1 extends Handler {
    @Override
    public void handle(Object request) {
        System.out.println("concrete handler 1 execute request. request: " + request);
        if (getNext() != null) {
            getNext().handle(request);
        }
    }
}

// 具体处理器 2
public class ConcreteHandler2 extends Handler {
    @Override
    public void handle(Object request) {
        System.out.println("concrete handler 2 execute request. request: " + request);
        if (getNext() != null){
            getNext().handle(request);
        }
    }
}

// 具体处理器 3
public class ConcreteHandler3 extends Handler {
    @Override
    public void handle(Object request) {
        System.out.println("concrete handler 3 execute request. request: " + request);
        if (getNext() != null) {
            getNext().handle(request);
        }
    }
}


public static void main(String[] args) {
    Handler concreteHandler1 = new ConcreteHandler1();
    Handler concreteHandler2 = new ConcreteHandler2();
    Handler concreteHandler3 = new ConcreteHandler3();

    concreteHandler1.setNext(concreteHandler2);
    concreteHandler2.setNext(concreteHandler3);

    concreteHandler1.handle("my request.");
}


Del código anterior, podemos ver que el patrón de Cadena de responsabilidad es realmente muy simple, pero hay algunos puntos a tener en cuenta:

  • En primer lugar, necesitamos inicializar toda la cadena de responsabilidad, es decir, configurar el siguiente de cada procesador .
  • Después de procesar cada procesador específico, es necesario llamar manualmente al método handle del siguiente procesador para realizar el siguiente paso de procesamiento. De hecho, el modo de método de plantilla también se puede usar aquí para la optimización.

La salida de la consola es la siguiente:

concrete handler 1 execute request. request: my request.
concrete handler 2 execute request. request: my request.
concrete handler 3 execute request. request: my request.


3. Demostración de ejemplo específico

Tomemos como ejemplo las vacaciones diarias . La solicitud de licencia será aprobada primero por su líder inmediato y luego irá al líder del departamento para su aprobación después de que se apruebe la aprobación. Después de que el líder del departamento la apruebe, finalmente se informará al departamento de recursos humanos para registrar la cantidad de días de licencia. Si en una empresa tradicional, necesitamos escribir un formulario de licencia a mano, luego ir a la oficina del líder directo, hacer que el líder directo firme, luego ir a la oficina del líder del departamento para firmar, y finalmente ir a la departamento de personal para enviar el formulario de licencia, que es equivalente a emitir Solo después de tres solicitudes se puede completar todo el proceso de solicitud de licencia.

Sin embargo, bajo la gestión de varios sistemas OA modernos, todo el proceso de licencia se vuelve más simple. Solo necesitamos iniciar una solicitud de licencia una vez, y luego su solicitud de licencia circulará automáticamente entre los aprobadores. En este momento, nuestra cadena de responsabilidad Los patrones vienen útil. el código se muestra a continuación:

// 请假抽象处理器
public abstract class DayOffHandler {
    private DayOffHandler next;

    public DayOffHandler getNext() {
        return next;
    }

    public void setNext(DayOffHandler next) {
        this.next = next;
    }
    public abstract void handle(String request);

}
// 直属 leader 处理
public class GroupLeaderHandler extends DayOffHandler {
    @Override
    public void handle(String request) {
        System.out.println("直属 leader 审查: " + request);
        System.out.println("同意请求");
        if (getNext() != null) {
            getNext().handle(request);
        }
    }
}
// 部门 leader 处理
public class DepartmentLeaderHandler extends DayOffHandler{
    @Override
    public void handle(String request) {
        System.out.println("部门 leader 审查: " + request);
        System.out.println("同意请求");
        if (getNext() != null) {
            getNext().handle(request);
        }
    }
}
// 人事处处理
public class HRHandler extends DayOffHandler {
    @Override
    public void handle(String request) {
        System.out.println("人事处审查: " + request);
        System.out.println("同意请求,记录请假");
        if (getNext() != null) {
            getNext().handle(request);
        }
    }
}



El código anterior define la clase de procesamiento abstracto de licencia y tres controladores específicos. Necesitamos conectar la inicialización del proceso de estos tres controladores en serie y ejecutarlos paso a paso, como se muestra en la siguiente imagen, para que el cliente El código final sea como sigue:

public static void main(String[] args) {

    DayOffHandler groupLeaderHandler = new GroupLeaderHandler();
    DayOffHandler departmentLeaderHandler = new DepartmentLeaderHandler();
    DayOffHandler hrHandler = new HRHandler();
    groupLeaderHandler.setNext(departmentLeaderHandler);
    departmentLeaderHandler.setNext(hrHandler);

    System.out.println("收到面试通知,需要请假");
    String request = "家中有事,请假半天,望批准";
    System.out.println("发起请求:");
    groupLeaderHandler.handle(request);
}


Como se puede ver en el código del cliente , primero creamos una instancia de tres controladores específicos y luego los conectamos en serie a través del método setNext , y solo necesitamos iniciar una solicitud de licencia al líder directo, y todo el proceso de aprobación se puede automatizar Después la implementación, no hay necesidad de ir a la oficina uno por uno para aplicar. El resultado después de la ejecución es el siguiente:

收到面试通知,需要请假
发起请求:
直属 leader 审查: 家中有事,请假半天,望批准
同意请求
部门 leader 审查: 家中有事,请假半天,望批准
同意请求
人事处审查: 家中有事,请假半天,望批准
同意请求,记录请假


4. Aplicación del modelo de cadena de responsabilidad en el código fuente

Cuando se trata del modo de cadena de responsabilidad, el más famoso es, por supuesto, el filtro en Servlet . En este sistema de interceptores y filtros , el modo de cadena de responsabilidad se utiliza para procesar cada solicitud por turno. Primero, veamos el uso de filtro Camino. La interfaz de filtro es la siguiente:

public interface Filter {
    default void init(FilterConfig filterConfig) throws ServletException {
    }

    void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;

    default void destroy() {
    }
}

  • FilterChain es una cadena de responsabilidad de Filter, y su código es el siguiente:
public interface FilterChain {
    void doFilter(ServletRequest var1, ServletResponse var2) throws IOException, ServletException;
}


public final class ApplicationFilterChain implements FilterChain {
    
    public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
        if (Globals.IS_SECURITY_ENABLED) {
            final ServletRequest req = request;
            final ServletResponse res = response;

            try {
                AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
                    public Void run() throws ServletException, IOException {
                        ApplicationFilterChain.this.internalDoFilter(req, res);
                        return null;
                    }
                });
            } catch (PrivilegedActionException var7) {
                Exception e = var7.getException();
                if (e instanceof ServletException) {
                    throw (ServletException)e;
                }

                if (e instanceof IOException) {
                    throw (IOException)e;
                }

                if (e instanceof RuntimeException) {
                    throw (RuntimeException)e;
                }

                throw new ServletException(e.getMessage(), e);
            }
        } else {
            this.internalDoFilter(request, response);
        }

    }

    private void internalDoFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
        if (this.pos < this.n) {
            ApplicationFilterConfig filterConfig = this.filters[this.pos++];

            try {
                Filter filter = filterConfig.getFilter();
                if (request.isAsyncSupported() && "false".equalsIgnoreCase(filterConfig.getFilterDef().getAsyncSupported())) {
                    request.setAttribute("org.apache.catalina.ASYNC_SUPPORTED", Boolean.FALSE);
                }

                if (Globals.IS_SECURITY_ENABLED) {
                    Principal principal = ((HttpServletRequest)request).getUserPrincipal();
                    Object[] args = new Object[]{request, response, this};
                    SecurityUtil.doAsPrivilege("doFilter", filter, classType, args, principal);
                } else {
                    filter.doFilter(request, response, this);
                }

            } catch (ServletException | RuntimeException | IOException var15) {
                throw var15;
            } catch (Throwable var16) {
                Throwable e = ExceptionUtils.unwrapInvocationTargetException(var16);
                ExceptionUtils.handleThrowable(e);
                throw new ServletException(sm.getString("filterChain.filter"), e);
            }
        } else {
            try {
                if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
                    lastServicedRequest.set(request);
                    lastServicedResponse.set(response);
                }

                if (request.isAsyncSupported() && !this.servletSupportsAsync) {
                    request.setAttribute("org.apache.catalina.ASYNC_SUPPORTED", Boolean.FALSE);
                }

                if (request instanceof HttpServletRequest && response instanceof HttpServletResponse && Globals.IS_SECURITY_ENABLED) {
                    Principal principal = ((HttpServletRequest)request).getUserPrincipal();
                    Object[] args = new Object[]{request, response};
                    SecurityUtil.doAsPrivilege("service", this.servlet, classTypeUsedInService, args, principal);
                } else {
                    this.servlet.service(request, response);
                }
            } catch (ServletException | RuntimeException | IOException var17) {
                throw var17;
            } catch (Throwable var18) {
                Throwable e = ExceptionUtils.unwrapInvocationTargetException(var18);
                ExceptionUtils.handleThrowable(e);
                throw new ServletException(sm.getString("filterChain.servlet"), e);
            } finally {
                if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
                    lastServicedRequest.set((Object)null);
                    lastServicedResponse.set((Object)null);
                }

            }

        }
    }
}


  • En el método internalDoFilter() , puede ver que FilterChain completo usa los filtros de matriz para almacenar cada filtro y su configuración, y usa pos para registrar qué filtro se atraviesa actualmente, y luego ejecuta el método doFilter del Filter obtenido . A diferencia del método de lista enlazada mencionado anteriormente, los enlaces aquí se almacenan en una matriz.
  • patrón de cadena de responsabilidad en primavera

El interceptor en SpringMVC también usa el patrón Cadena de responsabilidad . Primero observe la clase de procesamiento abstracto de Interceptor ;

public interface HandlerInterceptor {
    default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;
    }

    default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
    }

    default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
    }
}



En la clase de procesamiento abstracto, se definen tres métodos, que procesan el preprocesador, el posprocesador y el procesamiento después de que se completa todo el proceso. Los interceptores están conectados en serie a través de HandlerExecutionChain . En HandlerExecutionChain , debemos prestar atención a tres métodos: applyPreHandle , applyPostHandle y triggerAfterCompletion . Estos tres métodos ejecutan respectivamente los métodos preHandle , postHandle y afterCompletion definidos en el interceptor . Y también se puede ver en el código que, al igual que el filtro anterior, todos los interceptores se almacenan en la matriz de interceptores , y los métodos correspondientes se ejecutan en secuencia al atravesar la matriz de interceptores en los tres métodos.

public class HandlerExecutionChain {
    @Nullable
    private HandlerInterceptor[] interceptors;

    boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HandlerInterceptor[] interceptors = this.getInterceptors();
        if (!ObjectUtils.isEmpty(interceptors)) {
            for(int i = 0; i < interceptors.length; this.interceptorIndex = i++) {
                HandlerInterceptor interceptor = interceptors[i];
                if (!interceptor.preHandle(request, response, this.handler)) {
                    this.triggerAfterCompletion(request, response, (Exception)null);
                    return false;
                }
            }
        }

        return true;
    }

    void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv) throws Exception {
        HandlerInterceptor[] interceptors = this.getInterceptors();
        if (!ObjectUtils.isEmpty(interceptors)) {
            for(int i = interceptors.length - 1; i >= 0; --i) {
                HandlerInterceptor interceptor = interceptors[i];
                interceptor.postHandle(request, response, this.handler, mv);
            }
        }

    }

    void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex) throws Exception {
        HandlerInterceptor[] interceptors = this.getInterceptors();
        if (!ObjectUtils.isEmpty(interceptors)) {
            for(int i = this.interceptorIndex; i >= 0; --i) {
                HandlerInterceptor interceptor = interceptors[i];

                try {
                    interceptor.afterCompletion(request, response, this.handler, ex);
                } catch (Throwable var8) {
                    logger.error("HandlerInterceptor.afterCompletion threw exception", var8);
                }
            }
        }

    }
}


5. Resumen

El modo de cadena de responsabilidad también es un modo de diseño común. Los procesadores con diferentes responsabilidades se conectan en serie y el método de procesamiento de cada procesador se puede ejecutar a través de una solicitud. El remitente de la solicitud de esta manera solo necesita enviar una solicitud y no necesita conocer la estructura detallada del enlace; mientras que el receptor de la solicitud solo se preocupa por su propia lógica de procesamiento y pasa la solicitud al siguiente receptor después del procesamiento. se completa, por lo tanto Complete sus propias tareas, realizando así el desacoplamiento del remitente y el receptor de la solicitud. A partir del análisis del código fuente, podemos ver que aunque la estructura de lista enlazada se usa comúnmente en el modo de cadena de responsabilidad, los requisitos también se pueden cumplir mediante el uso de matrices y listas.

Autor: Jingdong Tecnología Canción Huichao

Fuente: Comunidad de desarrolladores de JD Cloud

 

El sistema operativo Maya desarrollado por el Ministerio de Defensa de la India, que reemplaza por completo a Windows Redis 7.2.0, y el sitio web oficial de la versión 7-Zip de mayor alcance fue identificado como un sitio web malicioso por Baidu Go 2 nunca traerá cambios destructivos a Go 1 Xiaomi lanzó CyberDog 2, más del 80% de la tasa de código abierto ChatGPT costo diario de alrededor de 700,000 dólares estadounidenses, OpenAI puede estar al borde de la bancarrota Se incluirá el software de meditación, fundado por la "primera persona de Linux en China" Apache Doris versión 2.0.0 Lanzamiento oficial: rendimiento de prueba ciega 10 veces mejorado, experiencia de análisis extremadamente rápida más unificada y diversa La primera versión del kernel de Linux (v0.01) interpretación de código fuente abierto Chrome 116 se lanza oficialmente
{{o.nombre}}
{{m.nombre}}

Supongo que te gusta

Origin my.oschina.net/u/4090830/blog/10098350
Recomendado
Clasificación