设计模式之责任链模式

定义与特点

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

注意:责任链模式也叫职责链模式。

主要优点

  1. 降低了对象之间的耦合度。该模式使得一个对象无须知道到底是哪一个对象处理其请求以及链的结构,发送者和接收者也无须拥有对方的明确信息。
  2. 增强了系统的可扩展性:若有新的过滤需求,只需要新增过滤器类并将其添加到责任链中即可,满足开闭原则

主要缺点

  1. 不能保证每个请求一定被处理。由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理。
  2. 对比较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。
  3. 职责链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于职责链的错误设置而导致系统出错,如可能会造成循环调用。

举个例子

javax包下servlet中的Filter过滤器对HttpServletRequest和HttpServletResponse两个对象的过滤操作

Request

复制代码
/*
请求
 */
class Request {

    String msg;

    public String getMsg() {
        return msg;
    }

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

    @Override
    public String toString() {
        return "Request{" +
                "msg='" + msg + '\'' +
                '}';
    }
}
复制代码

Response

复制代码
/*
响应
 */
class Response {

    String msg;

    public String getMsg() {
        return msg;
    }

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

    @Override
    public String toString() {
        return "Response{" +
                "msg='" + msg + '\'' +
                '}';
    }
}
复制代码

Filter

/*
过滤器接口
 */
interface Filter {

    boolean doFilter(Request request, Response response, FilterChain chain);

}

SensitiveFilter

复制代码
/*
敏感信息过滤器
 */
class SensitiveFilter implements Filter {

    @Override
    public boolean doFilter(Request request, Response response, FilterChain chain) {
        // 遇到敏感字符,修改后直接返回false
        if (request.getMsg().contains("996")) {
            request.setMsg(request.getMsg().replace("996", "955"));
            return false;
        }
        if (!chain.doFilter(request, response, chain)) {
            return false;
        }
        if (response.getMsg().contains("996")) {
            response.setMsg(response.getMsg().replace("996", "955"));
            return false;
        }
        return true;
    }
}
复制代码

URLAutomaticCompletionFilter

复制代码
/*
URL地址补全过滤器
 */
class URLAutomaticCompletionFilter implements Filter {

    @Override
    public boolean doFilter(Request request, Response response, FilterChain chain) {
        request.setMsg(request.getMsg().replace("cnblogs.com/pengsay", "https://www.cnblogs.com/pengsay"));
        if (!chain.doFilter(request, response, chain)) {
            return false;
        }
        response.setMsg(response.getMsg().replace("cnblogs.com/pengsay", "https://www.cnblogs.com/pengsay"));
        return true;
    }
}
复制代码

HTMLFilter

复制代码
/*
HTML过滤器
 */
class HTMLFilter implements Filter {

    @Override
    public boolean doFilter(Request request, Response response, FilterChain chain) {
        request.setMsg(request.getMsg().replace("<", "[").replace(">", "]"));
        if (!chain.doFilter(request, response, chain)) {
            return false;
        }
        response.setMsg(response.getMsg().replace("<", "[").replace(">", "]"));
        return true;
    }
}
复制代码

FilterChain

复制代码
/*
过滤器链
 */
class FilterChain implements Filter {

    private List<Filter> filters = new ArrayList<>();

    // 迭代器
    private Iterator<Filter> iterator;

    public FilterChain addFilter(Filter filter) {
        filters.add(filter);
        iterator = filters.iterator();
        return this;
    }

    // 对外接口
    public boolean filter(Request request, Response response) {
        return doFilter(request, response, this);
    }

    @Override
    public boolean doFilter(Request request, Response response, FilterChain chain) {
        if (!iterator.hasNext()) {
            // 如果过滤器已经执行完,则直接返回true
            return true;
        }
        Filter next = iterator.next();
        return next.doFilter(request, response, chain);
    }
}
复制代码

测试类

复制代码
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * @Author 14715
 * @Date 2022/5/25 13:22
 * @Version 1.0
 *
 * 责任链模式
 */
public class RocMain {
    public static void main(String[] args) {
        Request request = new Request();
        request.setMsg("cnblogs.com/pengsay——————995,<script type='text/javascript'>alert('I love program');</script>");
        Response response = new Response();
        response.setMsg("996——————cnblogs.com/pengsay,<h1>我爱编程</h1>");

        FilterChain fc = new FilterChain();
        fc.addFilter(new URLAutomaticCompletionFilter()).addFilter(new HTMLFilter()).addFilter(new SensitiveFilter());
        fc.filter(request, response);

        System.out.println(request);
        System.out.println(response);
    }
}
复制代码

测试结果

 

posted @   没有你哪有我  阅读(31)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
点击右上角即可分享
微信分享提示