`

管道过滤器模式(Pipe and Filter)与组合模式(修改)

 
阅读更多

 

转:http://haolloyin.blog.51cto.com/1177454/348277

之前在 benjielin 前辈的博客中看到“管道过滤器(Pipe-And-Filter)模式( http://bj007.blog.51cto.com/1701577/345677 )”,当时将文章中运用到的组合模式(Composite)与我刚刚写过的装饰模式(Decorator)和职责链模式(Chain of Responsibility)混为一谈,并希望用这后面两个模式进行代码实现,+_+

现在觉得还是先把那文章中的组合模式给具体实现一下吧,具体的文字描述请看上面文章链接哦。

在我的代码中,我假设的需求是:给定多个条件(即过滤器),遍历一本字典中的所有单词,将同时符合所有条件 的所有单词查询(过滤)出来。现假定需要过滤出“单词中同时包含a、b、cd字串,并且以"end”结尾,最后是单词的长度大于7 ”。

好了,看清了需求,得出类图如下:  

  1. // 字典  
  2. class  Dictionary {  
  3.  
  4.     // 字典里面有好多单词  
  5.     private  ArrayList<String> allWords;  
  6.  
  7.     public  Dictionary(ArrayList<String> allWords) {  
  8.         this .allWords = allWords;  
  9.     }  
  10.  
  11.     // 获取字典中所有单词  
  12.     public  ArrayList<String> getAllWords() {  
  13.         return  this .allWords;  
  14.     }  
  1. // 过滤器接口,只有 match() 方法  
  2. interface  IFilter {  
  3.     public  boolean  match(String word);  
  1. // 树叶型 过滤器,过滤单词中长度大于指定长度  
  2. class  LengthFilter implements  IFilter {  
  3.     private  int  length;  
  4.  
  5.     public  LengthFilter(int  length) {  
  6.         this .length = length;  
  7.     }  
  8.  
  9.     @Override  
  10.     public  boolean  match(String word) {  
  11.         if  (word.length() > length) {  
  12.             return  true ;  
  13.         }  
  14.         return  false ;  
  15.     }  
  1. // 树叶型 过滤器,过滤单词中包含有某个字符字串  
  2. class  ContainsFilter implements  IFilter {  
  3.     private  String subStr;  
  4.  
  5.     public  ContainsFilter(String subStr) {  
  6.         this .subStr = subStr;  
  7.     }  
  8.  
  9.     @Override  
  10.     public  boolean  match(String word) {  
  11.         if  (word.contains (subStr)) {  
  12.             return  true ;  
  13.         }  
  14.         return  false ;  
  15.     }  
  1. // 树叶型 过滤器,过滤单词中以某个字符字串结束  
  2. class  EndFilter implements  IFilter {  
  3.     private  String subStr;  
  4.  
  5.     public  EndFilter(String subStr) {  
  6.         this .subStr = subStr;  
  7.     }  
  8.  
  9.     @Override  
  10.     public  boolean  match(String word) {  
  11.         if  (word.endsWith (subStr)) {  
  12.             return  true ;  
  13.         }  
  14.         return  false ;  
  15.     }  
  1. // 抽象组合型 过滤器,类似于树枝节点  
  2. abstract  class  CompositeFilter implements  IFilter {  
  3.  
  4.     protected  ArrayList<IFilter > filters;  
  5.  
  6.     public  CompositeFilter() {  
  7.         this .filters = new  ArrayList<IFilter>();  
  8.     }  
  9.  
  10.     //   继续将 IFilter 接口中的 match() 声明为 abstract,  
  11.     // 由具体的过滤器子类进行实现  
  12.     public  abstract   boolean  match(String word);  
  13.  
  14.     // 添加过滤器链  
  15.     public  void  addFilters(ArrayList<IFilter > filters) {  
  16.         this .filters.addAll(filters);  
  17.     }  
  18.  
  19.     // 添加一个过滤器  
  20.     public  void  addFilter(IFilter filter) {  
  21.         this .filters.add(filter);  
  22.     }  
  23.  
  24.     // 既然是树枝过滤器,其下必有子过滤器  
  25.     public  ArrayList<IFilter> getFilters() {  
  26.         return  this .filters;  
  27.     }  
  1. // and  过滤器,树枝型 过滤器  
  2. class  AndFilter extends  CompositeFilter {  
  3.     @Override  
  4.     public  boolean  match(String word) {  
  5.         for (IFilter filter : super .filters) {  
  6.             if (!(filter.match(word))) {  
  7.                 return  false ;  
  8.             }  
  9.         }  
  10.         return  true ;  
  11.     }  
  1. // or  过滤器,树枝型 过滤器  
  2. class  OrFilter extends  CompositeFilter {  
  3.     @Override  
  4.     public  boolean  match(String word) {  
  5.         for (IFilter filter : super .filters) {  
  6.             if (filter.match(word)) {  
  7.                 return  true ;  
  8.             }  
  9.         }  
  10.         return  false ;  
  11.     }  

 

  1. // 管道  
  2. class  Pipe {  
  3.  
  4.     // 字典,相当于流入管道的数据流  
  5.     private  Dictionary dictionary;  
  6.  
  7.     // 用于保存过滤后的最终数据  
  8.     private  LinkedHashSet<String> theWords;  
  9.  
  10.     // 单词查询中需要用到的过滤器树  
  11.     private  IFilter filterTree;  
  12.  
  13.     // 用于保存字典中的所有单词,即数据流中的一个个数据  
  14.     private  ArrayList<String> allWords;  
  15.  
  16.     public  Pipe(Dictionary dictionary, IFilter  filterTree) {  
  17.         this .dictionary = dictionary;  
  18.         this .filterTree = filterTree;  
  19.         this .theWords = new  LinkedHashSet<String>();  
  20.     }  
  21.  
  22.     public  LinkedHashSet<String> getWords() {  
  23.         // 先搜索过滤字典中所有单词,再返回符合要求的单词集合  
  24.         this .allWords = dictionary.getAllWords();  
  25.         this .findWords();  
  26.         return  this .theWords;  
  27.     }  
  28.  
  29.     private  void  findWords() {  
  30.         // 对每个单词进行过滤  
  31.         for  (String word : allWords) {  
  32.             if (filterTree.match(word) == true ) {  
  33.                 this .theWords.add(word);  
  34.             }  
  35.         }  
  36.     }  

 

  1. // 测试类  
  2. public  class  Client {  
  3.     public  static  void  main(String[] args) {  
  4.  
  5.         // 创建过滤器树: 包含"a"、"b"、"cd"子串,以"end"结尾,长度 > 7  
  6.  
  7.         // 同时包含"a"、"b"、"cd"子串的过滤器         
  8.         CompositeFilter andFilter = new  AndFilter();  
  9.           
  10.         IFilter contain01 = new  ContainsFilter("a" );  
  11.         IFilter contain02 = new  ContainsFilter("b" );  
  12.         IFilter contain03 = new  ContainsFilter("cd" );  
  13.         andFilter.addFilter(contain01);  
  14.         andFilter.addFilter(contain02);  
  15.         andFilter.addFilter(contain03);  
  16.  
  17.         // 以 "end" 或 "END" 结尾的过滤器  
  18.         CompositeFilter orFilter = new  OrFilter();  
  19.           
  20.         IFilter end01 = new  EndFilter("end" );  
  21.         IFilter end02 = new  EndFilter("END" );  
  22.         orFilter.addFilter(end01);  
  23.         orFilter.addFilter(end02);  
  24.  
  25.         // 长度 > 7 的过滤器  
  26.         IFilter lengthFilter = new  LengthFilter(7 );  
  27.  
  28.         // 构建过滤器树,用根过滤器 将上面的所有过滤器组合起来  
  29.         CompositeFilter rootFilter new  AndFilter ();  
  30.           
  31.         rootFilter.addFilter(andFilter);  
  32.         rootFilter.addFilter(orFilter);  
  33.         rootFilter.addFilter(lengthFilter);  
  34.  
  35.         // 自定义一本字典里的所有单词  
  36.         ArrayList<String> allWords = new  ArrayList<String>();  
  37.         allWords.add("akkkk" );  
  38.         allWords.add("ab--b-cd--end" );  
  39.         allWords.add("abckk" );  
  40.         allWords.add("abdcend" );// 长度为6,不符合  
  41.         allWords.add("kakbkck" );  
  42.         allWords.add("a-b-cd-END" );  
  43.         allWords.add("bbcc" );  
  44.  
  45.         // 自定义一本字典  
  46.         Dictionary dictionary = new  Dictionary(allWords);  
  47.  
  48.         // 将字典、过滤器树传入管道  
  49.         Pipe pipe = new  Pipe(dictionary, rootFilter );  
  50.  
  51.         // 单词流在通过管道时被过滤,获取最终单词  
  52.         System.out.println(pipe.getWords());  
  53.     }  

测试结果:  

  1. [ab--b-cd--end, a-b-cd-END] 

如此一来,基本上解决了我在原来文章中的许多疑问(下面的是修改前的内容),根据 benjielin 前辈的提示,修改了原来完全不合理的地方,可看评论哦。

话说回来,原来的代码也太乱了,原因就是我完全理解错了 benjielin 前辈文章中关于组合模式中AndFilter 类、OrFilter 类的用处,也完全没弄明白组合模式究竟用于何处,呼...

小结:

1、Pipe 类中过滤的代码少了很多,只是调用过滤器的 match() 方法而已;

2、由 1 也相应地去除了由 Pipe 类来判断对象属于树叶还是树枝类型的逻辑,消去了坏味道;

3、原文中利用递归遍历过滤器树的方法一点都不合理,完全应该去除,当初是因为没理清思路;

4、改变主意,不用 职责链模式 来实现 管道过滤器模式了,因为现在我觉得那个模式应该实现不了 Composite 模式这样的功能,它最多也只能起到 的作用。

我的相关文章:

组合模式(Composite)的安全模式与透明模式 http://haolloyin.blog.51cto.com/1177454/347308

职责链模式(Chain of Responsibility)的Java实现 http://haolloyin.blog.51cto.com/1177454/342166

 

以下是修改前的部分内容,可不看,因为太不合理了。但我还是想保存着,毕竟是从以下代码修改而来的,所以可以参看benjielin前辈的评论来看。

类图如下:

   代码如下: 

//树叶型
过滤器,直接实现 IFilter ,过滤单词中长度大于 7

class
 LengthFilter implements
 IFilter {
	@Override
	public
 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);
	}

	@Override
	public
 boolean
 match(String word) {
		if
 (word.contains(super
.subStr)) {
			return
 true
;
		}
		return
 false
;
	}
}

 

// 过滤单词中以某个字符字串结束
的组合型过滤器

class
 EndFilter extends
 CompositeFilter {
	
	public
 EndFilter(String subStr) {
		super
(subStr);
	}

	@Override
	public
 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

分享到:
评论

相关推荐

    管道过滤器

    管道过滤器(Pipe and Filter)模式是一种经典的软件设计模式,它在Java和其他许多编程语言中广泛应用,尤其是在处理数据流和事件处理系统中。这个模式的主要思想是将复杂的处理任务分解成一系列可重用的过滤器组件...

    pipecodefiltter.zip_管道过滤_管道过滤器_管道风格

    这个"pipecodefiltter.zip"压缩包包含了一系列与管道过滤器相关的Java源代码文件,如Alphabetizer11.java、KWIC11.java、Input11.java、CircularShifter11.java、Pipe11.java、Filter11.java以及Output11.java,这些...

    Sugar:管道过滤器模式的简单实现

    管道过滤器运行中的pipe-filter pattern 。样本给定一个字符串列表,找到所有包含a , b和c字符的字符串。 // A list of string...stringList = Pipe . in(stringList) . then(data - &gt; data . stream() . filter...

    Java代码:KWIC程序示例

    在这个程序示例中,我们看到的是利用管道-过滤器(Pipe-Filter)设计模式来实现的。这种模式在处理大量数据流时特别有用,因为它允许将复杂任务分解为一系列简单的、可重用的组件。 管道-过滤器模式的核心思想是将...

    架构模式介绍(pdf格式)

    - **EJB/JBoss:** 在EJB容器中,管道过滤模式主要体现在容器与远程客户端之间的通信过程中。例如,EJB容器接收远程调用,并对其进行分析以提供相应的管理服务。EJB容器的底层通信模型可以视为多个过滤器和管道的...

    CalculatricePipeAndFilter_java_pipeline_

    在IT行业中,"CalculatricePipeAndFilter_java_pipeline_"这一标题暗示了一个使用Java实现的计算器应用,它采用了管道和过滤器(Pipe and Filter)设计模式。这个设计模式是一种常见于处理流水线系统的架构,尤其...

    PipeFilter_FileProcess.rar

    其中,"管道过滤器"(Pipe Filter)模式是一种设计模式,常用于处理大量数据流的应用程序,如文本处理、数据过滤和转换等。在处理千年虫问题时,这种模式可能被用来高效地分发、转换和验证数据,确保每个阶段都能...

    软件体系结构

    本项目聚焦于一种特定的设计模式——管道过滤器模式(Pipe-Filter Pattern),通过一系列组件对数据进行处理,最终达到预期的目标。本项目的主要目标是通过对一个具体实例的学习和实践,理解并掌握该设计模式的基本...

    Java多线程设计模式_清晰完整PDF版 Java多线程设计模式源代码

    2. 管道模式(Pipe and Filter):将复杂的任务分解为一系列相互连接的过滤器,每个过滤器在一个独立的线程中运行,提高了系统处理能力。Java的java.util.stream.Stream API可以实现类似的功能。 3. 线程池模式:...

    软工概论软件体系结构与设计模式推选PPT文档.ppt

    数据流风格是软件体系结构风格的一种,管道/过滤器结构拥有一组被称为过滤器(filter)的构件,这些构件通过管道(pipe)连接,管道将数据从一个构件传送到下一个构件。每个过滤器独立于其上游和下游的构件而工作,...

    KWIC.rar_KWIC ja_kwic_kwic oo

    4. 管道和过滤器(pipe and filter)实现:可能是一系列处理文本的脚本或程序,按照管道模型进行连接,例如,一个程序读取输入文本,下一个程序提取关键词,再下一个程序构建KWIC格式输出。 5. 示例数据:可能包含...

    TeeTime-Cpp:Pipe-and-Filter框架TeeTime的C ++参考实现

    这是管道过滤器(P&F)框架的C ++实现。 它基于的,但是已经通过多种方式适应了C ++,以支持现代C ++程序所依赖的所有语言功能。 它为P&F体系结构的建模和执行提供支持。 特征 开发和连接阶段的一种类型安全的方式...

    分布式架构模型.doc

    5. **管道与过滤器(Pipe and Filter)**:面向数据流编程,通过一系列相互连接的过滤器,每个过滤器处理数据的一个方面,最终形成完整的结果。这种模式在企业集成中广泛应用。 6. **映射与归约(MapReduce)**:Google...

    Angular2的管道Pipe的使用方法

    `@Pipe`装饰器内有一个对象,包含了管道的名字`name: 'filterUser'`。这个类需要实现`PipeTransform`接口,因此我们需要定义一个`transform`方法,这个方法接收输入值(allUsers)和可选参数(args),并返回处理后...

    系统架构师 软考 知识框架

    常见的软件架构风格有层次式架构(Layered Architecture)、客户端-服务器架构(Client-Server)、微服务架构(Microservices)、事件驱动架构(Event-Driven)、管道和过滤器架构(Pipe and Filter)等。...

    evolution-message-filter:与 Evolution 消息过滤器的“管道到程序”条件一起使用。 见 https

    本篇将详细探讨"evolution-message-filter",这是一种与Evolution消息过滤器相关的技术,特别是其"管道到程序"(pipe-to-program)条件的使用。 "管道到程序"是Evolution过滤器中的一个高级特性,它允许用户通过...

    rlwrap_filters:rlwrap过滤器

    使用rlwrap的-z选项调用过滤器: rlwrap -z "&lt;FILTER&gt;" &lt;OTHER&gt; 如果要使用多个过滤器,则可以使用rlwrap -z "&lt;FILTER&gt;" &lt;OTHER&gt; 随附的pipeline过滤器,如下所示: rlwrap -z 'pipeline &lt;FILTER1&gt;:&lt;FILTER2&gt;:&lt;ETC&gt;'...

    《软件架构》必考41题

    而管道-过滤器架构中,组件(filter)独立,通过连接器(pipe)传递数据,且处理顺序不影响结果的正确性。 8. 管道-过滤器架构特点与优缺点: - 优点:支持组件重用,组件独立,无共享状态,易于扩展和维护。 - ...

    simple-pipe:简单的管道库,如导管

    在 Haskell 中,管道通常用于实现过滤、转换、组合等操作,将数据流通过一系列处理步骤。`simple-pipe` 库利用了 Haskell 的高阶函数和类型系统,使得构建复杂的管道变得非常直观。它定义了一种名为 `Pipe` 的类型,...

Global site tag (gtag.js) - Google Analytics