管道过滤器模式(Pipe and Filter)与组合模式(修改)
?
??代码如下:?
//树叶型过滤器,直接实现 IFilter ,过滤单词中长度大于 7class LengthFilter implements IFilter {@Overridepublic boolean match(String word) {if (word.length() > 7) {return true;}return false;}}?
// 抽象组合型过滤器,类似于树枝节点abstract class CompositeFilter implements IFilter {private ArrayList<IFilter> filters;// 需要被过滤的单词中的字串protected String subStr;public CompositeFilter(String subStr) {this.filters = new ArrayList<IFilter>();this.subStr = subStr;}// 继续将 IFilter 接口中的 match() 声明为 abstract,// 由具体的过滤器子类进行实现public abstract boolean match(String word);// 添加过滤器链public void addFilters(ArrayList<CompositeFilter> filters) {this.filters.addAll(filters);}// 添加一个过滤器public void addFilter(IFilter filter) {this.filters.add(filter);}public ArrayList<IFilter> getNextFilter() {return this.filters;}}?
// 过滤单词中包含有某个字符子串的组合型过滤器class ContainsFilter extends CompositeFilter {public ContainsFilter(String subStr) {super(subStr);}@Overridepublic boolean match(String word) {if (word.contains(super.subStr)) {return true;}return false;}}?
// 过滤单词中以某个字符字串结束的组合型过滤器class EndFilter extends CompositeFilter {public EndFilter(String subStr) {super(subStr);}@Overridepublic boolean match(String word) {if (word.endsWith(super.subStr)) {return true;}return false;}}?
// 管道class Pipe {// 字典,相当于流入管道的数据流private Dictionary dictionary;// 用于保存过滤后的最终数据private LinkedHashSet<String> theWords;// 单词查询中需要用到的过滤器树private CompositeFilter filterTree;// 用于保存字典中的所有单词,即数据流中的一个个数据private ArrayList<String> allWords;public Pipe(Dictionary dictionary, CompositeFilter filterTree) {this.dictionary = dictionary;this.filterTree = filterTree;this.theWords = new LinkedHashSet<String>();}public LinkedHashSet<String> getWords() {// 先搜索过滤字典中所有单词,再返回符合要求的单词集合this.allWords = dictionary.getAllWords();this.findWords();return this.theWords;}private void findWords() {// 对每个单词进行过滤for (String word : allWords) {if(doFilter(word, filterTree) == true) {this.theWords.add(word);}}}// 递归遍历过滤器树private boolean doFilter(String word, CompositeFilter filterTree) {ArrayList<IFilter> filters = filterTree.getNextFilter();// 标志位,若为 true 则说明该单词符合条件boolean flag = true;for (IFilter filter : filters) {if(!filter.match(word)) {flag = false;break;}// 若是组合型过滤器,即树枝,则递归过滤if (filter instanceof CompositeFilter) {CompositeFilter thisFilter = (CompositeFilter) filter;doFilter(word, thisFilter);}}return flag;}}?
// 测试类public class Client {public static void main(String[] args) {// 创建过滤器: 包含"a"、"b"、"cd"子串,以"end"结尾,长度 > 7// 包含"a"、"b"、"cd"子串的过滤器CompositeFilter filter01 = new ContainsFilter("a");CompositeFilter filter02 = new ContainsFilter("b");CompositeFilter filter03 = new ContainsFilter("cd");// 以"end"结尾的过滤器CompositeFilter endFilter = new EndFilter("end");// 长度 > 7 的过滤器IFilter lengthFilter = new LengthFilter();// 构建过滤器树filter01.addFilter(filter02);filter01.addFilter(filter03);filter01.addFilter(endFilter);filter01.addFilter(lengthFilter);// 自定义一本字典里的所有单词ArrayList<String> allWords = new ArrayList<String>();allWords.add("akkkk");allWords.add("abkkbkcdend");allWords.add("abckk");allWords.add("abdcend");//长度为6,不符合allWords.add("kakbkck");allWords.add("kkkkkk");allWords.add("bbcc");// 自定义一本字典Dictionary dictionary = new Dictionary(allWords);// 将字典、过滤器树传入管道Pipe pipe = new Pipe(dictionary, filter01);// 单词流在通过管道时被过滤,获取最终单词System.out.println(pipe.getWords());}}??测试结果:
[abkkbkcdend]?呼…代码太长了,总算是写出来了,从字典中过滤出我们需要的单词了。但是,面对这样的结构,我有如下疑问:
1、上面在 Client 类中并没有“真正”使用到组合模式,它不是一棵过滤器树充其量也只是作为一条过滤器链而已,没有体现出组合模式那种“层次”,即一个中间过滤器下面还一棵树,在 Client 类中构建过滤器树时其实是一个根节点 filter01 下面链接着其他4个过滤器对象;所以,在代码中的 Pipe 类中进行递归过滤时用得并不实际;
2、我在想,管道过滤器模式中是不是一定要用到组合模式来体现出具有层次之别的过滤器族?如果不是的话,那么用职责链模式来实现我上面的效果我认为会更加便利、快速(接下来我会尝试实现一下),因为在这里体现不出 组合模式(Composite)强调的“整体-部分”的特性(也很有可能是我理解不到位);
3、其实,上面实现的过滤 String 变量可以直接用正则表达式实现,那样子更更更简单,由此不免感叹一下:正则表达式太强大了;
本文出自 “蚂蚁” 博客,请务必保留此出处http://haolloyin.blog.51cto.com/1177454/348277