IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 【学习笔记】责任链模式(Chain Of Responsibility) -> 正文阅读

[Java知识库]【学习笔记】责任链模式(Chain Of Responsibility)

0 设计模式

不了解设计模式的小伙伴可以通过这篇文章了解一下什么是设计模式

https://blog.csdn.net/qq_42874315/article/details/120006447?spm=1001.2014.3001.5502

1 责任链模式

责任链模式是我个人认为比较重要的一种设计模式,在我日常的编码中也较常用到,责任链模式的本质就是过滤器,责任链模式可以使过滤条件自由组合,降低了代码的耦合度,并且扩展性非常高,面向责任链过滤,而不面向具体的过滤器去过滤。

原理图

在这里插入图片描述

2 实现思路

在这里插入图片描述

3 需要的类

  1. 过滤器接口

  2. 多个实现过滤器接口的具体过滤器

  3. 实现过滤器接口的具体责任链(在责任链的doFilter中可以提前就对过滤器进行注册)

    责任链中需要一个额外的方法add,用来添加具体的过滤器

    需要一个含有多个Filter集合(注册过滤器用的)

  4. 消息实体(往过滤器中传入的)

  5. 额外的一个测试方法(需要注意的是,提前将过滤器添加到责任链中,面向责任链过滤,而不面向具体的过滤器去过滤)

4 具体实现

4.1 Filter(创建过滤器接口)

/**
 * @Author ChenJiahao(程序员五条)
 * @Date 2021/8/1 13:44
 */
public interface Filter {
    boolean doFilter(Message m);
}

4.2 多个实现过滤器接口的具体过滤器

4.2.1 FaceFilter(将:) 替换为 V)

/**
 * @Author ChenJiahao(程序员五条)
 * @Date 2021/8/1 13:45
 */
public class FaceFilter implements Filter {
    @Override
    public boolean doFilter(Message m) {
        // 处理msg
        String r = m.getMsg();
        r = r.replace(":)","^V^");
        m.setMsg(r);
        return true;
    }
}

4.2.2 HtmlFilter(将< 替换为 [ 将> 替换为 ])

/**
 * @Author ChenJiahao(程序员五条)
 * @Date 2021/8/1 13:45
 */
public class HtmlFilter implements Filter {
    @Override
    public boolean doFilter(Message m) {
        // 处理msg
        String r = m.getMsg();
        r = r.replace('<','[');
        r = r.replace('>',']');
        m.setMsg(r);
        return true;
    }
}

4.2.3 SensitiveFilter(将996 替换为 007)

/**
 * @Author ChenJiahao(程序员五条)
 * @Date 2021/8/1 13:54
 */
public class SensitiveFilter implements Filter {
    @Override
    public boolean doFilter(Message m) {
        // 处理msg
        String r = m.getMsg();
        r = r.replace("996","007");
        m.setMsg(r);
        return true;
    }
}

4.3 FilterChain(实现过滤器接口的具体责任链)

/**
 * @Author ChenJiahao(程序员五条)
 * @Date 2021/8/1 13:47
 */
public class FilterChain implements Filter {
    List<Filter> filters = new ArrayList<>();

    public FilterChain add(Filter f){
        filters.add(f);
        return this;
    }

    @Override
    public boolean doFilter(Message m) {
        for (Filter filter : filters) {
            if (!filter.doFilter(m)){
                return false;
            }
        }
        return true;
    }
}

4.4 Message(消息实体,根据实际情况完全可以用一个字符串去替代)

/**
 * @Author ChenJiahao(程序员五条)
 * @Date 2021/8/1 13:44
 */
public class Message {
    String name;
    String msg;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

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

4.5 测试类

注:在责任链的doFilter中可以提前就对过滤器进行注册,这样在测试类中就不用再注册过滤器了(具体示例见扩展)

/**
 * @Author ChenJiahao(程序员五条)
 * @Date 2021/8/1 13:50
 */
public class Main {
    public static void main(String[] args) {
        Message message = new Message();
        message.setMsg("大家好:),<script>,我是程序员五条,大家都是996");
        // 过滤表情和HTML的链条
        FilterChain filterChain = new FilterChain();
        filterChain.add(new FaceFilter()).add(new HtmlFilter());

        // 过滤996的链条
        FilterChain filterChain1 = new FilterChain();
        filterChain1.add(new SensitiveFilter());

        // 两个链条合并(也可以单用)
        filterChain.add(filterChain1);

        // 执行链条
        filterChain.doFilter(message);
        System.out.println(message);
    }
}

5 扩展(链式拦截)

5.1 思路

  1. 定义多条拦截规则
  2. 只要其中一条不符合,这条消息就可以视为非法消息

5.2 实例:校验SQL

5.2.1 SqlInterceptor(拦截器接口)

5.2.2 拦截接口的实现类

IllegalKeywordsInterceptor(SQL非法关键字校验,只允许查询select)

/**
 * SQL非法关键字校验
 * @Author ChenJiahao(程序员五条)
 * @Date 2021/8/17 15:08
 */
@Component
public class IllegalKeywordsInterceptor implements SqlInterceptor{

    static List<String> illegalKeywordsList = new ArrayList<>();

    static {
        illegalKeywordsList.add("update ");
        illegalKeywordsList.add("drop ");
        illegalKeywordsList.add("alter ");
        illegalKeywordsList.add("delete ");
        illegalKeywordsList.add("insert ");
        illegalKeywordsList.add("create ");
        illegalKeywordsList.add("grant ");
        illegalKeywordsList.add("perpare ");
        illegalKeywordsList.add("execute ");
        illegalKeywordsList.add("deallocate ");
        illegalKeywordsList.add("truncate ");
    }

    @Override
    public void doInterceptor(String sql) {
        // SQL全部转小写
        String lowerSql = sql.toLowerCase();
        for (String illegalKeywords : illegalKeywordsList) {
            if (lowerSql.contains(illegalKeywords)){
                throw new SqlCheckException("SQL中包含非法关键字:" + illegalKeywords);
            }
        }
    }
}

SqlLengthInterceptor(SQL长度校验)

/**
 * SQL长度校验
 * @Author ChenJiahao(程序员五条)
 * @Date 2021/8/20 11:20
 */
public class SqlLengthInterceptor implements SqlInterceptor{
    @Override
    public void doInterceptor(String sql) throws SqlCheckException {
        if (sql.length() < 20) {
            throw new SqlCheckException("SQL长度至少需要大于等于20");
        }
    }
}

5.2.3 SqlCheckInterceptorChain(拦截链)

/**
 * SQL校验链
 * @Author ChenJiahao(程序员五条)
 * @Date 2021/8/17 15:09
 */
public class SqlCheckInterceptorChain implements SqlInterceptor{

    List<SqlInterceptor> interceptors = new ArrayList<>();

    private SqlCheckInterceptorChain add(SqlInterceptor sqlInterceptor){
        interceptors.add(sqlInterceptor);
        return this;
    }

    @Override
    public void doInterceptor(String sql) {
        add(new IllegalKeywordsInterceptor());
        add(new SqlLengthInterceptor());
        for (SqlInterceptor interceptor : interceptors) {
            interceptor.doInterceptor(sql);
        }
    }
}

5.2.4 测试类

这里我已经提前将多个拦截规则提前注册到拦截链中了(见拦截链代码的doInterceptor()),所以在调用的时候只传入消息即可

/**
 * @Author ChenJiahao(程序员五条)
 * @Date 2021/8/17 15:15
 */
public class Main {
    public static void main(String[] args) {
        new SqlCheckInterceptorChain().doInterceptor("update public.user set username = '程序员五条' where id = 1");
    }
}

6 思维导图

在这里插入图片描述

7 示例源码地址

https://github.com/ChenJiahao0205/design-pattern/tree/master

最后

我是通过马士兵老师的视频和菜鸟教程学习的,部分内容可能会有雷同

想阅读更多设计模式相关文章,欢迎到我的专栏【设计模式学习笔记】、【设计模式】中去查看

在23篇设计模式文章发布完成之后,我会公开完整的思维导图,点关注,不迷路

感谢大家看到这里,文章如有不足,欢迎大家指出;彦祖点个赞吧彦祖点个赞吧彦祖点个赞吧,欢迎关注程序员五条

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-09-11 18:40:35  更:2021-09-11 18:41:45 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 17:21:29-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码