专栏首页mathor设计模式——责任链

设计模式——责任链

问题引入

 假设有一个论坛,很多人可以在上面发消息,但是这些消息,有的需要过滤敏感字眼,有的又需要修改关键字,举个简单的例子

String msg = "你好,中国澳门皇家赌场,<html>性感xx在线...</html>,:)";

 就上面这消息,我们就有两处要进行屏蔽,首先是敏感字:“中国澳门皇家赌场,性感”,其次是html代码“<html>,</html>”要修改成“[html],[/html]”,不然消息发出来可能会对结果产生影响。  针对上面的问题,我们通常都是这么做的

public class Main() {
    public static void main(String[] args) {
        String msg = "你好,中国澳门皇家赌场,<html>性感xx在线...</html>,:)";
        msg = msg.replace("中国澳门皇家赌场","").replace("性感","").replace("<","[").replace(">","]");
        System.out.println(msg);
    }
}

责任链

 上面只是非常简单的一种写法,但是接下来我们要站在面向对象的角度去思考这个程序应该怎么写。马士兵老师说:“设计模式最基本的要求就是先写测试

public class Main() {
    public static void main(String[] args) {
        String msg = "你好,中国澳门皇家赌场,<html>性感xx在线...</html>,:)";
        msg = msg.replace("中国澳门皇家赌场","").replace("性感","").replace("<","[").replace(">","]");
        System.out.println(msg);
    }
}

 信息过滤有两种,一种是html代码过滤,一种是敏感字过滤,所以我们干脆创建一个接口Filter,然后创建一个HtmlFilter类实现接口的doFilter方法,另一个SesitiveFilter类也实现doFilter方法

//Filter接口
public interface Filter {
    String doFilter(String str);
}

//HtmlFilter类
public class HtmlFilter implements Filter {
    
    @Override
    public String doFilter(String str) {
        String r = str.replace("<", "[").replace(">","]");
        return r;
    }
}

//SesitiveFilter类
public class SesitiveFilter implements Filter {

    @Override
    public String doFilter(String str) {
        String r = str.replace("中国澳门皇家赌场","").replace("性感","");
        return r;
    }
}

//MsgProcessor类
public class MsgProcessor {
    private String msg;
    Filter[] filters = {new HtmlFilter(),new SesitiveFilter()};
    public void set(String msg) {
        this.msg = msg;
    }
    public String get() {
        return msg;
    }
    public String process() {
        String r = msg;
        for(Filter f : filters)
            r = f.doFilter(r);
        return r;
    }
}

 整个代码文件结构如下图所示:

 这样写,有两个好处,假设我需要新增一个过滤规则,只需要新建一个类,实现接口的方法,然后将这个类增加到Filter数组中即可。还有一个好处,就是可以使过滤规则有一定的顺序,比方说一个新生来上学,他需要先交钱,再领书,再领被子,再进教室......Filter数组里匿名对象的顺序,就是执行的顺序。  可以用一幅图来表示责任链这种设计模式的过程:

 黑色的箭头可以理解为一个消息的输入,经过三个黄色过滤器后,最终输出到数据库或者其他地方。

引入新的责任链

 再考虑一个问题,假如又有一系列的责任链,需要将新的责任链插在原责任链的中间执行(具体见下图),应该怎么做?

 用一个新的类FilterChain,里面有一个ArrayList,专门存放各种实现Filter的类

//FilterChain类
import java.util.*;
public class FilterChain {
    List<Filter> filters = new ArrayList<Filter>();
    public FilterChain add(Filter f) {
        this.filters.add(f);
        return this;
    }
    public String doFilter(String str) {
        String r = str;
        for(Filter f:filters) 
            r = f.doFilter(r);
        return r;
    }
}

 MsgProcessor类也要修改

//MsgProcessor类
public class MsgProcessor {
    private String msg;
    //Filter[] filters = {new HtmlFilter(),new SesitiveFilter()};
    FilterChain fc;
    public FilterChain getFc() {
        return fc;
    }
    public void setFc(FilterChain fc) {
        this.fc = fc;
    }
    public void set(String msg) {
        this.msg = msg;
    }
    public String get() {
        return msg;
    }
    public String process() {
        return fc.doFilter(msg);
    }
}

 最后是Main

//Main类
public class Main {
    public static void main(String[] args) {
        String msg = "你好,中国澳门皇家赌场,<html>性感xx在线...</html>,:)";
        MsgProcessor mp = new MsgProcessor();
        mp.set(msg);
        FilterChain fc = new FilterChain();
        fc.add(new HtmlFilter()).add(new SesitiveFilter());
        mp.setFc(fc);
        String result = mp.process();
        System.out.println(result);
    }
}

 整个执行过程再讲述一遍,首先Main方法把msg传给MsgProcess,然后创建一个FilterChain对象,调用其add方法,往里面添加很多种Filter,然后将FilterChain对象也传给MsgProcess,最后调用MsgProcess中的process方法。process方法会执行fc.doFilter(msg),doFilter函数是将fc中的所有Filter执行一遍。具体执行流程可以看下图:

服务器客户端责任链

 新的问题,客户端Client发送一个消息,经过Filter1,Filter2,然后传给服务器端Server。接下来服务器端要给一个消息反馈给客户端,因此要依次经过Filter2,Filter1(很明显,过去和回来经过Filter的顺序肯定是相反的)  这有点栈的思想在里面,将Client端发送出去时遇到的各种Filter压栈,然后在Server端传输回来的时候依次弹栈,类似的思想。  首先客户端和服务器端的类肯定要有

//Server端
public class ServerFilter {
    private String str;

    public String getStr() {
        return str;
    }

    public void setStr(String str) {
        this.str = str;
    }
}

//Client端
public class ClientFilter {
    private String str;

    public String getStr() {
        return str;
    }

    public void setStr(String str) {
        this.str = str;
    }
}

//Filter接口
public interface Filter {
    void doFilter(ClientFilter client,ServerFilter server,FilterChain chain);
}

//HtmlFilter类
public class HtmlFilter implements Filter {
    
    @Override
    public void doFilter(ClientFilter client,ServerFilter server,FilterChain chain) {
        client.setStr(client.getStr().replace("<", "[").replace(">","]") + "---HtmlFilter()");
        chain.doFilter(client, server, chain);
        server.setStr(server.getStr() + "---HtmlFilter()");
    }
}

//SesitiveFilter类
public class SesitiveFilter implements Filter {

    @Override
    public void doFilter(ClientFilter client,ServerFilter server,FilterChain chain) {
        client.setStr(client.getStr().replace("中国澳门皇家赌场","").replace("性感","") + "---SesitiveFilter()");
        chain.doFilter(client, server, chain);
        server.setStr(server.getStr() + "---SesitiveFilter()");
    }
}

//FilterChain类
import java.util.*;
public class FilterChain implements Filter{
    int idx = 0;
    List<Filter> filters = new ArrayList<Filter>();
    public FilterChain add(Filter f) {
        this.filters.add(f);
        return this;
    }
    @Override
    public void doFilter(ClientFilter client, ServerFilter server, FilterChain chain) {
        if(idx == filters.size())
            return;
        Filter f = filters.get(idx);
        idx++;
        f.doFilter(client, server, chain);
    }
}

MsgProcessor类
public class MsgProcessor {
    private String msg;
    //Filter[] filters = {new HtmlFilter(),new SesitiveFilter()};
    FilterChain fc;
    public FilterChain getFc() {
        return fc;
    }
    public void setFc(FilterChain fc) {
        this.fc = fc;
    }
    public void set(String msg) {
        this.msg = msg;
    }
    public String get() {
        return msg;
    }
    public void process(ClientFilter client,ServerFilter server) {
        fc.doFilter(client, server, fc);
    }
}

//Main类
public class Main {
    public static void main(String[] args) {
        String msg = "你好,中国澳门皇家赌场,<html>性感xx在线...</html>,:)";
        MsgProcessor mp = new MsgProcessor();
        FilterChain fc = new FilterChain();
        fc.add(new HtmlFilter()).add(new SesitiveFilter());
        mp.setFc(fc);
        ClientFilter client = new ClientFilter();
        client.setStr(msg);;
        ServerFilter server = new ServerFilter();
        server.setStr("Server");;
        mp.process(client, server);
        System.out.println(client.getStr());
        System.out.println(server.getStr());
    }
}

结语

 马士兵老师说:“不要问学什么有用学什么没用,直接去招聘网站看看,现在招什么人才,需要会什么技术”

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • File

    mathor
  • 给定一个字符串数组,按照字典顺序进行从小到大的排序

     假设字符串数组是str[] = {"ab","cd","ef"},很明显答案就是”abcdef“最小,其实这是一道贪心问题,我的想法是将字符串数组进行内的字符...

    mathor
  • 图的常见算法

     图是由一系列点和边的集合构成的,一般有邻接矩阵和邻接表两种表示方式,c/c++可以看我的这篇文章:搜索(1)  这篇文章主要讲java语言中图的相关算法。首...

    mathor
  • 回调函数

    什么是回调函数,上面的问题说的是不是很空洞,不是太形象,下面是知乎上的一位网友给的答案:

    LiosWong
  • fastjson:javabean按字段(field)序列化存储为Map并反序列化

    大部分json工具对java对象整体序列化都提供了简单的调用方式,以fastjson为例: Model model = new Model(); String ...

    用户1148648
  • fastjson:javabean按字段(field)序列化存储为Map并反序列化改进

    需求说明 最近的项目应用到redis数据库,需要将java bean存储在redis数据库。因为需要对数据库中的某个字段进行修改,所以在redis上不能用简单的...

    用户1148648
  • Lombok学习

    Lombok是一个Java库,能自动插入编辑器并构建工具,简化Java开发。通过添加注解的方式,不需要为类编写getter或eques等常规方法,同时可以自动化...

    神秘的寇先森
  • Java基础——Annotation

    注解相当于一种标记,在程序中加了注解就等于为程序打上了某种标记,javac编译器,开发工具和其他程序可以用反射来了解你的类及各种元素上有无何种标记,看你有什么标...

    羊羽shine
  • (19)Struts2_表单标签

    qubianzhong
  • Java自动化测试(接口操作优化 15)

    由于发起post请求的时候,它可能为json格式,也可能为form表单格式。所以对他进行提取

    zx钟

扫码关注云+社区

领取腾讯云代金券