¿Este es el "modelo de cadena de responsabilidad"?

Prefacio


Solo una cabeza calva puede volverse más fuerte.

El texto se ha incluido en mi artículo destacado de GitHub, bienvenido a Star : https://github.com/ZhongFuCheng3y/3y

Recientemente, cuando estaba mirando el código del proyecto, encontré el "Modelo de Cadena de Responsabilidad", así que quería dedicar algo de tiempo a escribir sobre qué es el Modelo de Cadena de Responsabilidad.

No sé cómo aprenden todos los patrones de diseño. Por lo general, solo los aprendo cuando los uso o cuando me pongo en contacto. De lo contrario, siento que es fácil de olvidar después de aprender, y no puedo entender por qué se usan los patrones de diseño (porque no hay una escena real para que yo use).

He actualizado algunos artículos sobre patrones de diseño antes, y creo que la escritura está "bien", y los estudiantes interesados ​​pueden ir a mi GitHub y buscar " patrones de diseño " por palabra clave para encontrar los artículos correspondientes.

image.pngimage.png

1. ¿Qué es el modelo de cadena de responsabilidad?

Antes de hablar sobre el modelo de cadena de responsabilidad, hablemos primero de " filtros ".

Creo que todo el mundo debe haber aprendido el filtro. Lo aprenderemos cuando aprendamos Servlet por primera vez Filter. Cuando aprendamos Struts2, aprenderemos Interceptor. Cuando aprendamos SpringMVC, aprenderemos HandlerInterceptor.

Pero no importa qué marco aprendamos, descubrimos que realmente hace Filtertal cosa al final. Para decirlo sin rodeos:

  • Coloque todos los filtros en FilterChain y ejecute cada filtro a su vez.

He hablado sobre Filter, HandlerInterceptor e Interceptor en mi GitHub. Si desea revisar, puede ingresar y buscar las palabras clave " filter " " Struts2 " " SpringMVC "

image.png ¿Por qué tenemos que hablar de "filtros" en el modelo de cadena de responsabilidad? Hablaré de eso más tarde, no te preocupes.

1.1 Mata a Ao Bing y huevos

Por ejemplo: imagina nuestra solicitud normal como un montón de artículos diversos. Hay frijoles de arroz, huevos, muñecos de juguete Ao Bing y otros artículos diversos. image.pngAhora lo que queremos son frijoles de arroz , huevos y juguetes Ao Bing filtrados. Entonces podemos hacer dos filtros para filtrar los juguetes y huevos de Ao Bing.

De la forma más rápida, podemos escribir ifpara hacer frente a este requisito, el siguiente código.

Una solicitud, usamos Requestobjetos para representar:

public class Request {
    // 请求的数据
    private String data;

    public String getData() {
        return data;
    }
    public void setData(String data) {
        this.data = data;
    }
}

Para la solicitud, debemos tener una interfaz para manejar la solicitud, usamos Handlerpara indicar:

public class Handler {

    public void handlerRequest(Request request) {

        // 得到请求的数据
        String data = request.getData();

        if (data.contains("鸡蛋")) {
            filterEgg(data);
        }
        if (data.contains("敖丙工具")) {
            filterAoBing(data);
        }
        // 我到这里就能拿到米豆了。
    }

    private void filterAoBing(String data) {
        //doSomething
    }

    private void filterEgg(String data) {
        //doSomething
    }
}

No sabes si estás familiarizado con el código anterior. De todos modos, estoy muy familiarizado con él. Muchas veces escribo código como este (muchos códigos en realidad son así).

1.2 ¿Cómo matar a Ao Bing y los huevos con más gracia?

En cierto año y cierto mes llegó el producto y me dijo que necesitaba agregar un nuevo tipo de "repollo" para filtrar

En un mes y año determinados, el producto vino a decirme que era necesario agregar un nuevo tipo de "pierna de pollo" que quiero filtrar.

En cierto mes y año, llegó el producto y me dijo que se debía agregar un nuevo tipo de "cabeza de pollo" para filtrar

Entonces, nuestro procesamiento de Handler puede "expandirse", ¿o sí?

public class Handler {

    public void handlerRequest(Request request) {

        // 得到请求的数据
        String data = request.getData();

        if (data.contains("鸡蛋")) {
            filterEgg(data);
        }
        if (data.contains("敖丙工具")) {
            filterAoBing(data);
        }
        if (data.contains("白菜")) {
            filterBaiCai(data);
        }
        if (data.contains("鸡头")) {
            filterJiTou(data);
        }
        if (data.contains("鸡腿")) {
            filterJiTui(data);
        }
        // 我到这里就能拿到米豆了。
    }

    private void filterJiTou(String data) {
        //doSomething
    }

    private void filterJiTui(String data) {
        //doSomething
    }

    private void filterAoBing(String data) {
        //doSomething
    }

    private void filterEgg(String data) {
        //doSomething
    }
}

Obviamente, si el flujo de procesamiento cambia significativamente (es necesario agregar o eliminar uno de los procesos), entonces necesito cambiar handlerRequestel código cada vez , agregando / modificando / eliminando uno ify uno de los métodos de procesamiento.

Una forma más orientada a objetos es la siguiente: cada método de procesamiento se abstrae en una clase y cada clase realiza sus propias funciones .

无论是过滤敖丙还是过滤鸡蛋还是过滤米豆,做的事都是过滤。我们就可以将其抽象成接口。于是我们就有一个接口,多个实现类

public interface Filter {
    // 过滤
    void doFilter(String data);
}

class FilterEgg implements Filter {

    @Override
    public void doFilter(String data) {
        //doSomething
    }
}

class FilterAoBing implements Filter {

    @Override
    public void doFilter(String data) {
        //doSomething
    }
}

class FilterBaiCai implements Filter {

    @Override
    public void doFilter(String data) {
        //doSomething
    }
}

class FilterJiTou implements Filter {

    @Override
    public void doFilter(String data) {
        //doSomething
    }
}

每个各司其职的Filter都有可能被执行,我们可以将其串成一条链,抽象一层对外只暴露一个方法来替代if。于是我们可以写出一个FilterChain

public class FilterChain {
    List<Filter> filters = new ArrayList<>();

    public FilterChain() {
        filters.add(new FilterEgg());
        filters.add(new FilterAoBing());
        filters.add(new FilterBaiCai());
        filters.add(new FilterJiTou());
    }
    public void processData(String data) {
        for (Filter filter : filters) {
            filter.doFilter(data);
        }
    }
}

改造过后,我们的Handler就长这个样子了:

public class Handler {
    public void handlerRequest(Request request) {
        // 得到请求的数据
        String data = request.getData();
        FilterChain filterChain = new FilterChain();
        // 处理数据
        filterChain.processData(data);
    }
}

如果我告诉你,这种的处理方式就是责任链模式,你会怎么想?

二、为什么责任链模式?

再来回顾一下,我做了些什么:

  1. 将处理的各个流程抽象为各个类(本来Handler里边有多个if方法)

  2. 将多个类用Chain链起来,暴露一个方法给Handler使用

  3. done

下面我画了一张对比图:image.png是不是很简单?说到底还是抽象了一层(将每个处理抽象为一个类而已)。image.png那为什么要这样干?如果我要增加一个处理流程,我是得新增一个处理类,然后在链上增加相对应的类。操作也的确如此。

这不麻烦吗?要便捷的话,我还不如直接增加一个if,一个处理方法来得方便呢。

用责任链模式的好处就是分工明确,解耦,容易维护

  • 将多个条件判定分散到各个的处理类上,相对于if else耦合性相对较低。

  • 增加一个具体的Handler处理类,不会影响到BaseHandler的代码

责任链模式的缺点:

  • 项目里边会有多个具体Handler类(因为每种处理都抽象为一个类,所以会有多个类)

  • 不好调试,初看代码时不好阅读。(对外只是一个doChain方法,而里边由多个处理类来组成,还得看相应的调用顺序)

三、再来聊聊责任链模式

我们从上面也可以看到责任链模式主要有以下特点:

  • 一个Handler接口,多个Handler处理类

  • 多个Handler处理类串起来形成一条链

有这两个特点我就称这些代码运用了责任链模式。在翻阅资料或者看书的时候,你可能会看到:“责任链和不纯责任链”

  • 纯:请求执行到某个具体的Handler,该Handler要么自行处理然后结束请求,要么不处理继续往下给别的Handler执行。

  • 不纯:请求执行到某个具体的Handler,该Handler自行处理了,继续往下给别的Handler执行。

还有就是将各个具体的Handler串成一条链,这里边的实现会有各式各样的:

  • 在我例子里是直接new出一个ArrayList,然后在构造方法里边代码手动add到ArrayList的

  • 有可能会在代码里边每个具体Handler都会记录自己下一个Handler是谁

  • 有可能将Handler的初始化放在XML上

  • ….//反正各种操作最终还是会将各个Handler串起来

其实不必要在意纯和不纯的责任链模式,我们学设计模式是为了学它的思想

四、看看JavaWeb的Filter

在文章最开头我就说了我们以前学过的Filter,其实Filter就是用了责任链模式。我们来简单看看代码:

我们在使用Filter过滤器的时候,要么在XML上配置<filter>,要么在代码上写上注解@WebFilter(filterName = "",urlPatterns = "")

这些配置都会在Web容器启动的时候被读取,读完这些配置,会将你写的Filter过滤器加到FilterChain里边:image.png我们可以看到Filter接口下有很多都实现了doFilterimage.pngJavaWeb的Filter实际用到的也是责任链模式。

最后

设计模式本身不是一件很复杂的东西,像门面模式,模板方法模式都非常容易理解。学完了会有一种感觉:“啊?就这?

重要的是学完能不能用到实际的工作中,这是非常难能可贵的。我们写代码按照自身的思维写if else是非常简单的,而设计模式往往需要绕一个圈才能把功能实现。

但是,合理运用设计模式的代码是非常好维护的。如果你懂设计模式,那代码会看起来非常清晰。如果你不懂设计模式,你就会感叹“这代码是真的骚阿”(这就是我…)。

好好学习,希望有朝一日,别人看到我的代码,在背后说「这人写的代码是真的骚,牛逼阿」。

参考资料:

  • 《设计模式之禅》

  • https://www.cnblogs.com/tanshaoshenghao/p/10741160.html



如果大家想要实时关注我更新的文章以及分享的干货的话,可以关注我的公众号Java3y

  • 获取海量视频资源

  • Obtenga un hermoso mapa mental en Java

  • Obtenga la ruta de aprendizaje de Java

  • Obtenga herramientas de desarrollo comunes

  • Jing Mei toda la razón Hao el libro electrónico PDF


¡Responde " 888 " en la cuenta oficial para obtenerlo! !

image.png

Haz clic en uno para verlo y compartirlo con amigos, ¡es muy importante para mí! !



Supongo que te gusta

Origin blog.51cto.com/15082392/2590095
Recomendado
Clasificación