一个过滤敏感字眼的小故事
有这样一个场景:现在我们要将“:- , 敏感词汇”经过一个过滤器之后变成“^v^,不敏感词汇”我们该怎样去写这段代码。
简单替换
我们可能会首先会想到这样的一段代码如下:
package simplefilter;
public class Main {
public static void main(String[] args) {
String str = ":-,敏感词汇";
String result = str.replaceAll(":-","^v^");
System.out.println(result);
}
}
这段代码完全能够解决我们现在的问题,但是这些过滤的规则没有进行有效的封装所以代码不能够有效的复用。假设我们又有一句话需要相同的过滤我们则需要重复上面的代码去替换。
封装过滤
为了达到复用的效果我们进行了以下的改进,下图为类的的总体结构功能图:
我们将这些替换字符串的操作按照功能封装到一些类中,由于这些类的共同点就是都有字符串处理的方法所以我们定义一个有字符串处理的方法的接口Filter并且让其它处理的实现类去实现这个接口。
具体的过滤步骤就是让字符串通过一个Filter的数组的过滤动作然后得到目标数组。
代码如下:
package dpfilter;
public interface Filter {
public abstract String process(String str);
}
package dpfilter;
public class SisFilter implements Filter{
@Override
public String process(String str) {
return str.replaceAll("敏感","不敏感");
}
}
package dpfilter;
public class SmileFilter implements Filter{
@Override
public String process(String str) {
return str.replaceAll(":-","^V^");
}
}
package dpfilter;
public class Processor {
Filter[] filters = {new SisFilter(),new SmileFilter()};
public String result(String process) {
String result = process;
for(Filter f : filters) {
result = f.process(result);
}
return result;
}
}
package dpfilter;
public class Main {
public static void main(String[] args) {
String sis = "敏感词汇 :-";
//经过一个过滤器链
Processor pro = new Processor();
String process = pro.result(sis);
System.out.println(process);
}
}
插入链条的过滤
现在我又有了另一个需求,我们有两组过滤器的链条我们如何才能够将他们合并呢?而且这个合并不是简单的追加有可能是将第二个链条插入第一个链条的某一个地方。
我们的思路就是把过滤器的链条当做是一个大大的过滤器,所以我们将在定义一个过滤器链条的类里面维护一个数组,并且实现Filter接口。
具体代码如下:
package newdpfilter;
import java.util.ArrayList;
import java.util.List;
public class FilterChain implements Filter{
private List<Filter> filters = new ArrayList<Filter>();
public String process(String str) {
String result = str;
for(Filter f : filters) {
result = f.process(result);
}
return result;
}
public FilterChain addFilter(Filter f) {
filters.add(f);
return this;
}
public List getFilters() {
return filters;
}
public void setFilters(List filters) {
this.filters = filters;
}
}
package newdpfilter;
public class Processor {
FilterChain fc;
public String result(String process) {
return fc.process(process);
}
public FilterChain getFc() {
return fc;
}
public void setFc(FilterChain fc) {
this.fc = fc;
}
}
package newdpfilter;
public class NumFilter implements Filter{
@Override
public String process(String str) {
return str.replaceAll("666","777");
}
}
package newdpfilter;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
String sis = "敏感词汇 :- 666";
//经过一个过滤器链
Processor pro = new Processor();
FilterChain chain = new FilterChain();
//由于addFilter之后会返回一个chain所以这里可是使用链式编程
chain.addFilter(new SmileFilter())
.addFilter(new SisFilter());
FilterChain chain1 = new FilterChain();
chain1.addFilter(new NumFilter());
chain.addFilter(chain1); pro.setFc(chain);
String process = pro.result(sis);
System.out.println(process);
}
}
除此之外其它的类不变。
模拟过滤器
我们将需求进一步加大,我们现在想要模拟JavaWeb中的过滤器。过滤器要求的是request的内容顺序通过过滤器,而response逆序通过过滤器。如下图:
这个设计思路就非常的精巧,总体的流程图如下:
我们想要过滤的字符串任然封装在request与response中。当我们想过滤时直接调用FilterChain里的process方法。根据访问的次数我们会依次得到过滤器数组中不同的过滤器的处理。当我们的访问数量达到我们过滤器数组的大小时我们就就停止处理。这时候我们的request就通过了所有的过滤器。紧接着我们会去对response进行处理因为整个process结构如下图所示:
图中的高亮代码会一直深入的调用,直到我们的访问数量达到我们过滤器数组的大小时我们就就停止处理。当停止处理时图中的response中的代码就会执行也就是response中的内容进行过滤。当过滤完当前层的response代码就会达到上一层response过滤的相同位置,直到全部都过滤完。形象的表述图就是上面的流程图。具体代码如下(完整版):
package finaldpfilter;
public interface Filter {
public abstract void process(Request request,Response response,FilterChain chain);
}
package finaldpfilter;
import java.util.ArrayList;
import java.util.List;
public class FilterChain implements Filter{
private List<Filter> filters = new ArrayList<Filter>();
int index = 0;
public FilterChain addFilter(Filter f) {
filters.add(f);
return this;
}
public List getFilters() {
return filters;
}
public void setFilters(List filters) {
this.filters = filters;
}
@Override
public void process(Request request, Response response,FilterChain chain) {
if(index == filters.size()) return;
Filter f = filters.get(index);
index++;
f.process(request, response, chain);
}
}
package finaldpfilter;
public class Request {
String requestStr;
public String getRequestStr() {
return requestStr;
}
public void setRequestStr(String requestStr) {
this.requestStr = requestStr;
}
}
package finaldpfilter;
public class Response {
String ResponseStr;
public String getResponseStr() {
return ResponseStr;
}
public void setResponseStr(String responseStr) {
ResponseStr = responseStr;
}
}
package finaldpfilter;
public class SisFilter implements Filter{
@Override
public void process(Request request, Response response,FilterChain chain) {
request.requestStr = request.requestStr.replaceAll("敏感","不敏感") + "---SisFilter---";
chain.process(request, response, chain);
response.ResponseStr += "---SisFilter---";
}
}
package finaldpfilter;
public class SmileFilter implements Filter{
@Override
public void process(Request request, Response response,FilterChain chain) {
request.requestStr = request.requestStr.replaceAll(":-","^V^") + "----SmileFilter---";
chain.process(request, response, chain);
response.ResponseStr += "----SmileFilter---";
}
}
package finaldpfilter;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
String sis = "敏感词汇 :-";
//经过一个过滤器链
Request request = new Request();
request.setRequestStr(sis);
Response response = new Response();
response.setResponseStr("zhuliu7");
FilterChain chain = new FilterChain();
chain.addFilter(new SmileFilter())
.addFilter(new SisFilter());
chain.process(request, response,chain);
System.out.println(request.getRequestStr());
System.out.println(response.getResponseStr());
}
}
如果你读懂了以上的文章那么我就大概差不多可以说你读懂了责任链模式。