假设有一个论坛,很多人可以在上面发消息,但是这些消息,有的需要过滤敏感字眼,有的又需要修改关键字,举个简单的例子
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());
}
}
马士兵老师说:“不要问学什么有用学什么没用,直接去招聘网站看看,现在招什么人才,需要会什么技术”