设计模式之责任链模式【Java实现】

news/2024/5/19 12:28:33 标签: java, 设计模式, 责任链模式

责任链(Chain of Resposibility) 模式

概念

责任链(chain of Resposibility) 模式:为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者 通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它位置。属于对象行为型模式。

  • 抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。

  • 具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将请求转给他的后继者。

  • 客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,他不关心处理细节和请求的传递过程。

代码

需求1:a1 -> a2 -> a3

实现先a1处理完交给a2,a2处理完再交给a3的逻辑,即: a1 -> a2 -> a3

java">public class Teacher {

    private String name;

    public Teacher(String name) {
        this.name = name;
    }

    // 下一个处理的老师;1、链条的引用点
    private Teacher next;

    public Teacher getNext() {
        return next;
    }

    public void setNext(Teacher next) {
        this.next = next;
    }

    void handlerRequest() {
        System.out.println(this + "正在处理。。。。。。。。");
        // 2、下一个继续
        if (next != null) {
            next.handlerRequest();
        }
    }

    @Override
    public String toString() {
        return "Teacher{" +
                "name='" + name + '\'' +
                '}';
    }
}

java">public class MainTest {
    public static void main(String[] args) {
        Teacher a1 = new Teacher("a1");
        Teacher a2 = new Teacher("a2");
        Teacher a3 = new Teacher("a3");

        // 3、构造链条
        // a1->a2->a2
        a1.setNext(a2);
        a2.setNext(a3);

        a1.handlerRequest();

    }
}

测试结果:

java">Teacher{name='a1'}正在处理。。。。。。。。
Teacher{name='a2'}正在处理。。。。。。。。
Teacher{name='a3'}正在处理。。。。。。。。

需求2:1->2->3->本人->3->2->1

这个也就是我们学习过的Filter了

代码实现:

① Filter 接口

java">public interface Filter {
    void doFilter(Request request,Response response,FilterChain chain);
}
java">@Data
public class Request {
    // 请求内容
    String msg;

    public Request(String msg) {
        this.msg = msg;
    }
}

java">@Data
public class Response {

    // 响应内容
    private String content;

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

② Filter 的三个实现类
在这里插入图片描述

java">public class HttpFilter implements Filter {
    @Override
    public void doFilter(Request request, Response response, FilterChain chain) {
        // 第一个filter的功能
        request.msg += ">>>";

        System.out.println("HttpFilter ... doFilter之前");
        // 放行
        chain.doFilter(request, response, chain);
        System.out.println("HttpFilter ... doFilter之后");
    }
}
java">public class CharacterFilter implements Filter {
    @Override
    public void doFilter(Request request, Response response, FilterChain chain) {
        // 功能
        request.msg += "====";

        System.out.println("CharacterFilter ... doFilter之前");
        // 放行
        chain.doFilter(request, response, chain);
        System.out.println("CharacterFilter ... doFilter之后");
    }
}
java">public class EncodingFilter implements Filter {
    @Override
    public void doFilter(Request request, Response response, FilterChain chain) {
        // 功能
        request.msg += "oooo";

        System.out.println("EncodingFilter ... doFilter之前");
        // 放行
        chain.doFilter(request, response, chain);
        System.out.println("EncodingFilter ... doFilter之后");
    }
}

③ 我们的目标方法

java">public class My {
    void hello() {

        System.out.println("调用my.hello()方法");
    }
}

```![在这里插入图片描述](https://img-blog.csdnimg.cn/7b173906028e45c7926d7b944096d929.png)


④ 维护链条

```java
/**
 * 靠他维护链条
 * handlerExecutionChain
 *
 * @author zhuicat
 * @since 2023/8/13 8:19
 */
public class FilterChain implements Filter {

    // 游标:记录当前执行的步骤
    int cursor;

    // Filter 的链
    List<Filter> filterChain = new ArrayList<>();

    // 最终要执行的目标方法
    My target;

    // 添加 filter 方法
    void addFilter(Filter filter) {
        filterChain.add(filter);
    }

    @Override
    public void doFilter(Request request, Response response, FilterChain chain) {
        // 执行第一个 filter ,一次往下

        // 游标小于总数量filter一直往下获取执行
        if (cursor < filterChain.size()) {
            Filter filter = filterChain.get(cursor);
            cursor++;
            // 执行 filter
            filter.doFilter(request, response, chain);
        } else {
            // filter执行完了,需要执行目标方法了
            target.hello();
        }
    }

    public My getTarget() {
        return target;
    }

    public void setTarget(My target) {
        this.target = target;
    }
}

⑤ 主方法

java">public class MainTest {
    public static void main(String[] args) {
        FilterChain chain = new FilterChain();

        // web.xml
        HttpFilter httpFilter = new HttpFilter();
        CharacterFilter characterFilter = new CharacterFilter();
        EncodingFilter encodingFilter = new EncodingFilter();
        chain.addFilter(httpFilter);
        chain.addFilter(characterFilter);
        chain.addFilter(encodingFilter);

        chain.setTarget(new My());


        // filter 如何链式执行
        chain.doFilter(new Request("hello,world"), new Response("dddddddddddddddddd"), chain);
    }
}

⑥ 执行结果

java">HttpFilter ... doFilter之前
CharacterFilter ... doFilter之前
EncodingFilter ... doFilter之前
调用my.hello()方法
EncodingFilter ... doFilter之后
CharacterFilter ... doFilter之后
HttpFilter ... doFilter之后

完成上述需求


http://www.niftyadmin.cn/n/4943040.html

相关文章

【Vue前端】设置标题用于SEO优化

原文作者&#xff1a;我辈李想 版权声明&#xff1a;文章原创&#xff0c;转载时请务必加上原文超链接、作者信息和本声明。 文章目录 1.vue全局配置2.创建并暴露getPageTitle方法3.通过全局前置守卫设置title4.页面上引用title5.项目使用中英文翻译&#xff0c;title失效 1.vu…

【C/C++】可变参数列表

目录 一、可变参数宏&#xff08;VA_ARGS__&#xff09;二、C风格不定参使用函数调用时参数的压栈顺序及内存使用 三、C风格不定参数的使用 一、可变参数宏&#xff08;VA_ARGS__&#xff09; #include <stdio.h>//...表示不定参数列表&#xff0c;__VA_ARGS__是宏&…

Android中的二级列表-ExpandableListView

Android中的二级下拉列表&#xff0c;类似于某Q的分组&#xff0c;采用ExpandableListView实现&#xff0c;适配器方法如下。 先看效果图&#xff1a;有四个分组&#xff0c;每个分组下都有一些子条目&#xff0c;可以跟着父条目展开而显示 实现代码&#xff1a; 一级列表是一…

uniapp微信小程序区分正式版,开发版,体验版

小程序代码区分是正式版&#xff0c;开发版&#xff0c;还是体验版 通常正式和开发环境需要调用不同域名接口&#xff0c;发布时需要手动更换 或者有些东西不想在正式版显示&#xff0c;只在开发版体验版中显示&#xff0c;也需要去手动隐藏 官方没有明确给出判断环境的方法&a…

C语言入门教程,C语言学习教程(非常详细)第三章 变量和数据类型

在《数据在内存中的存储》一节中讲到&#xff1a; 计算机要处理的数据&#xff08;诸如数字、文字、符号、图形、音频、视频等&#xff09;是以二进制的形式存放在内存中的&#xff1b;我们将8个比特&#xff08;Bit&#xff09;称为一个字节&#xff08;Byte&#xff09;&…

Threejs学习02——使用dat.gui实现主动控制立方体相关操作

使用dat.gui实现主动控制立方体相关操作 这是一个非常简单基础的threejs的学习应用&#xff01;在上一章学习threesj中我们实现立方体在坐标轴中来回移动&#xff0c;那都是通过我们的代码写死的效果&#xff0c;然后立方体的颜色都是通过代码写死的&#xff0c;这一章我们来给…

原生js快速获取路由param

方法一&#xff1a;正则法 function getQueryString(name) {var reg new RegExp((^|&) name ([^&]*)(&|$), i);var r window.location.search.substr(1).match(reg);if (r ! null) {return unescape(r[2]);}return null; }// 这样调用&#xff1a; alert(GetQ…

【校招VIP】java语言考点之ConcurrentHashMap1.7和1.8

考点介绍&#xff1a; ConcurrentHashMap是JAVA校招面试的热门考点&#xff0c;主要集中在1.7和1.8的底层结构和相关的性能提高。 理解这个考点要从map本身的并发问题出发&#xff0c;再到hashTable的低性能并发安全&#xff0c;引申到ConcurrentHashMap的分块处理。同时要理解…