按照《POSA(面向模式的软件架构)》里的说法,管道过滤器(Pipe-And-Filter)应该属于架构模式,因为它通常决定了一个系统的基本架构。管道过滤器和生产流水线类似,在生产流水线上,原材料在流水线上经一道一道的工序,最后形成某种有用的产品。在管道过滤器中,数据经过一个一个的过滤器,最后得到需要的数据。
clip_p_w_picpath001
如果感觉抽象的话大家可以想想网上购物。在网上购物的时候一般都会用到搜索和过滤功能。多数网店不仅支持一次性过滤,而且还可以支持在过滤到的结果中层层过滤直至到找到你所钟爱的商品。本文就提出一种简化的实现。由于考虑到过滤器不仅可能是单一条件的,也可能是多个条件的组合。所以就通过Composite Pattern引入了Composite Filter以支持And、Or以及Not等组合条件过滤。类结构图如下:
clip_p_w_picpath003
代码实现如下:
InBlock.gifnamespace FilterDemo
InBlock.gif{
InBlock.gif        public enum CATAGORY { Food, Drink, Cloth, Office, Other };

InBlock.gif        public class Goods
InBlock.gif        {
InBlock.gif                public int Price { private set; get; }
InBlock.gif                public CATAGORY Category { private set; get; }
InBlock.gif                public Goods(CATAGORY category, int price)
InBlock.gif                {
InBlock.gif                        Category = category;
InBlock.gif                        Price = price;
InBlock.gif                }
InBlock.gif        }

InBlock.gif        public interface Filter
InBlock.gif        {
InBlock.gif                bool Match(Goods goods);
InBlock.gif        }

InBlock.gif        public class PriceRangeFilter : Filter
InBlock.gif        {
InBlock.gif                int min;
InBlock.gif                int max;
InBlock.gif                public PriceRangeFilter(int min, int max)
InBlock.gif                {
InBlock.gif                        this.min = min;
InBlock.gif                        this.max = max;
InBlock.gif                }
InBlock.gif                public bool Match(Goods goods)
InBlock.gif                {
InBlock.gif                        return (goods.Price >= min && goods.Price <= max);
InBlock.gif                }
InBlock.gif        }

InBlock.gif        public class CategoryFilter : Filter
InBlock.gif        {
InBlock.gif                CATAGORY category;
InBlock.gif                public CategoryFilter(CATAGORY category)
InBlock.gif                {
InBlock.gif                        this.category = category;
InBlock.gif                }
InBlock.gif                public bool Match(Goods goods)
InBlock.gif                {
InBlock.gif                        return (goods.Category == category);
InBlock.gif                }
InBlock.gif        }

InBlock.gif        public class CompositeFilter : Filter
InBlock.gif        {
InBlock.gif                protected ArrayList filters = new ArrayList();
InBlock.gif                public void AddFilters( params Filter[] filters)
InBlock.gif                {
InBlock.gif                        this.filters.AddRange(filters);
InBlock.gif                }
InBlock.gif                public void AddFilter(Filter filter)
InBlock.gif                {
InBlock.gif                        this.filters.Add(filter);
InBlock.gif                }
InBlock.gif                public bool Match(Goods goods)
InBlock.gif                {
InBlock.gif                        return false;
InBlock.gif                }
InBlock.gif        }

InBlock.gif        public class AddFilter : CompositeFilter
InBlock.gif        {
InBlock.gif                public bool Match(Goods goods)
InBlock.gif                {
InBlock.gif                        foreach (Filter filter in filters)
InBlock.gif                        {
InBlock.gif                                if (!filter.Match(goods))
InBlock.gif                                        return false;
InBlock.gif                        }
InBlock.gif                        return true;
InBlock.gif                }
InBlock.gif        }

InBlock.gif        public class OrFilter : CompositeFilter
InBlock.gif        {
InBlock.gif                public bool Match(Goods goods)
InBlock.gif                {
InBlock.gif                        foreach(Filter filter in filters)
InBlock.gif                        {
InBlock.gif                                if(filter.Match(goods))
InBlock.gif                                        return true;
InBlock.gif                        }
InBlock.gif                        return false;
InBlock.gif                }
InBlock.gif        }
InBlock.gif}

至此,Pipe-And-Filter模式的Filter部分设计已经完成。剩下的就是设计管道,并安装上述各种Filter。