拦截过滤器模式
拦截过滤器模式:允许开发人员通过不同的标准,过滤一组对象,通过逻辑操作把他们以解耦的方式把他们连接起来,他可以组合多个标准来获得单一标准。在Java web中主要用于统一接收并过滤客户端的请求,根据过滤器的选择,将请求传送给对应目标处理程序。
场景
现有一段文字,按要求过滤将文符过滤出来
例如:
输入:"5UCHoddo&+Qo4.~*cQ"
过滤字母输出:"5&+4.~*"
过滤数字输出:"UCHoddo&+Qo.~*cQ"
过滤字符输出:"5UCHoddoQo4cQ"
实现
IFilter:接口,用于统一的过滤标准
XXXFilterImpl:IFilter的实现类,用于IFilter中方法的具体实现
FilterManager:用于管理多个过滤器
deo:演示类
目录结构
过滤接口
- IFilter.java
public interface IFilter {
String doFilter(String content);
}
具体实现类
- LetterFilterImpl.java
/**
* 具体的过滤类,用于过滤字母a~z,A~Z
* @author admian
*
*/
public class LetterFilterImpl implements IFilter {
private String letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
@Override
public String doFilter(String content) {
StringBuffer sb = new StringBuffer();
char[] cs = content.toCharArray();
for (char c : cs) {
if (!letter.contains((c + "").toUpperCase())) {
sb.append(c);
}
}
return new String(sb);
}
}
- NumberFilterImpl .java
/**
* 具体的过滤类,用于过滤数字0~9
* @author admian
*
*/
public class NumberFilterImpl implements IFilter {
private String number = "0123456789";
@Override
public String doFilter(String content) {
StringBuffer sb = new StringBuffer();
char[] cs = content.toCharArray();
for (char c : cs) {
if (!number.contains(c + "")) {
sb.append(c);
}
}
return new String(sb);
}
}
- CharFilterImpl.java
/**
* 具体的过滤类,用于过滤非数字0~9和非字母a~z,A~Z
* @author admian
*
*/
public class CharFilterImpl implements IFilter {
private String letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private String number = "0123456789";
@Override
public String doFilter(String content) {
StringBuffer sb = new StringBuffer();
char[] cs = content.toCharArray();
for (int i = 0; i < cs.length; i++) {
if (letter.contains((cs[i] + "").toUpperCase()) && number.contains(cs[i] + "")) {
sb.append(cs[i]);
}
}
return new String(sb);
}
}
过滤器管理类
- FilterManager.java
public class FilterManager {
List<IFilter> filters = new LinkedList<>();
public void addFilter(IFilter filter) {
filters.add(filter);
}
public String excute(String content) {
for (IFilter filter : filters) {
content = filter.doFilter(content);
}
return content;
}
public void excuteRemove(IFilter filter) {
filters.remove(filter);
}
}
过滤器演示类
- deo.java
public class deo {
public static void main(String[] args) {
String content = "5UCHoddo&+Qo4.~*cQ";
FilterManager manager = new FilterManager();
LetterFilterImpl f1 = new LetterFilterImpl();
NumberFilterImpl f2 = new NumberFilterImpl();
CharFilterImpl f3 = new CharFilterImpl();
manager.addFilter(f1);
manager.addFilter(f2);
manager.addFilter(f3);
String s1 = manager.excute(content);
System.out.println("过滤字母、数字、字符:"+s1);
manager.excuteRemove(f3);
String s2 = manager.excute(content);
System.out.println("过滤字母、数字:"+s2);
manager.excuteRemove(f2);
String s3 = manager.excute(content);
System.out.println("过滤字母:"+s3);
manager.excuteRemove(f1);
String s4 = manager.excute(content);
System.out.println("无过滤:"+s4);
}
}
结果:
过滤字母、数字、字符:
过滤字母、数字:&+.~*
过滤字母:5&+4.~*
过滤字母:5UCHoddo&+Qo4.~*cQ
通过新的语言特性,我们可以简化设计模式的使用,更快速的开发程序。这是简单的过滤器模式希望不足,有什么请大家多多指教
总结
在写实现类的时候将* StringBuffer sb = new StringBuffer(); 写在了IFilter接口中实现类方法doFilter()的外面,作为为全局变量。当时觉得没有什么错误,但是在运行的时候发现结果总是会多一遍字符串,如输入 “5UCHoddo&+Qo4.~*cQ” 要求过滤字母和数字结果会输出 “&+.~&+.~*” **。
我在想是不是我哪里错了?就那么多类,我首先想到是FilterManager方法中的excute() 方法在运行过程中多运行了几次或者是变量传递出现错误,然后在 excute() for 循环前后各加了打印变量的值 如图:
可以看出是这里出的错,但是不知道是不是方法中调用 doFilter() 的时候是否有错,接着我又在 NumberFilterImpl 类中加入打印并将 FilterManager 中的打印注释,如图:
经过以上种种分析,问题就在 StringBuffer 中那么问题出在哪里,这时我想起StringBuffer中具有缓存功能,是不是缓存???可能是,那么每次调用 doFilter() 的时候我们把他清空,结果是对的。但是真的是缓存的原因么???再仔细回想看 deo 类中写的,发现我们在每一次调用 excuteRemove() 方法的时候在调用实现类 doFilter() 方法的时候使用的 StringBuffer 是全局变量,存在于这个类的起始,所以我们使用 StringBuffer 的 append() 方法的时候有可能 StringBuffer 中存在上一次中的数据。
如果有不同意见请多多指教!