管道模式

来源:互联网 发布:林心如律师发声明知乎 编辑:程序博客网 时间:2024/05/16 15:16

今天接触了管道模式,在这里总结一下自己的理解。不足之处请各位多多指教

在软件开发中,我们会听到三个词,就是流、管道和过滤器。

我认为:

流:数据

管道:数据传输的通道(载体)

过滤器:过滤掉在管道中不符合要求的数据

原始数据经过管道传输到另一端产生最终数据。

在生活中,好比 原水经过管道(一层层的过滤,沉淀、去杂质、消毒)到管道另一端形成了纯净水。

在系统中,我们经常会根据业务逻辑对一个数据集进行频繁的处理、我们通常可以把它都封装在BLL中,

这个BLL就可以看作是一个管道,通过一系列的if else判断来满足业务逻辑的需求,最终过滤出最终的数据,

这种方式可以达到目的,但是不够灵活变通,如果我要添加或修改一个业务需求,就要去整理整个的逻辑实现。(模块内高内聚)


通过现象看本质,我们不可能把所有原水的过滤放在一个管道中去提纯,将一个大的处理流程进行详细的划分,

划分成每个小模块,每个模块只关心自己的业务逻辑处理,然后将它们有序的结合起来。这样的划分,

就相当于在过滤纯净水的管道,加了若干个阀门,我们把处理的逻辑放在每个阀门上,然后有序的组合,

第一道阀门调节什么,第二道调节什么..... 经过一层层处理,得到最终数据。 

如ASP.NET 19个管道事件,每个管道事件处理不同的逻辑,有序组合。




我们常见的一个需求就是 需要在当前查询结果的基础上继续查询数据,这里就可以使用管道模式。


C#代码示例:

    //定义过滤器接口    public interface IFilter    {        //数据是否匹配        bool IsMatch(Goods goods);    }


    /// <summary>    /// 过滤器合成抽象类(组合过滤条件)    /// </summary>    public abstract class CompositeFilter : IFilter    {        protected List<IFilter> filters = new List<IFilter>();        public abstract bool IsMatch(Goods goods);        public void AddFilter(IFilter filter)        {            this.filters.Add(filter);        }        public void AddFilterRange(List<IFilter> filters)        {            this.filters.AddRange(filters);        }    }
    //And过滤器(条件)    public class AndFilter : CompositeFilter    {        //重写匹配方法,交由具体的过滤去具体实现        public override bool IsMatch(Goods goods)        {            return filters.All(filter => filter.IsMatch(goods));        }    }
    //Or过滤器    public class OrFilter : CompositeFilter    {        public override bool IsMatch(Goods goods)        {            return filters.Any(filter => filter.IsMatch(goods));        }    }
初始化商品信息:

List<Goods> glist = new List<Goods>()

{       new Goods(){ Name="雕牌洗衣粉 中", Price=19},       new Goods(){ Name="黑人牙膏", Price=16},       new Goods(){ Name="云南白药牙膏", Price=35},       new Goods(){ Name="康师傅绿茶", Price=3},       new Goods(){ Name="洗发露", Price=42},       new Goods(){ Name="铁观音 小袋", Price=15},};

定义管道:

 public class Pipe    {        private IFilter filter;        public List<Goods> Goods { get; private set; }      //原数据        public List<Goods> newGoods { get; private set; }   //过滤产生的最终数据        public List<Goods> Filter(List<Goods> goods, IFilter filter)        {            this.newGoods = new List<Goods>();            this.Goods = goods;            this.filter = filter;            DoFilter();            return newGoods;        }        //过滤操作        private void DoFilter()        {            //对每个商品进行具体的匹配操作,不符合的过滤掉            foreach (var good in Goods.Where(g => filter.IsMatch(g)))            {                this.newGoods.Add(good);            }        }    }

自定义具体的过滤器:

  //名称过滤    public class GoodsNameFilter : IFilter    {        private string name;        public GoodsNameFilter(string name)        {            this.name = name;        }        public bool IsMatch(Goods goods)        {            if (goods.Name.Contains(name))                return true;            return false;        }    }    //价格区间过滤    public class GoodsPriceRangeFilter : IFilter    {        int min;        int max;        public GoodsPriceRangeFilter(int min, int max)        {            this.min = min;            this.max = max;        }        public bool IsMatch(Goods goods)        {            if (goods.Price >= min && goods.Price <= max)                return true;            return false;        }    }

最终实现:

 //过滤器合成            AndFilter filterCombination = new AndFilter();            AndFilter andFilter = new AndFilter();            //自定义过滤器            var priceFilter = new GoodsPriceRangeFilter(15, 20);            var nameFilter = new GoodsNameFilter("牙膏");            //and条件过滤数据集            andFilter.AddFilter(priceFilter);            andFilter.AddFilter(nameFilter);            //组合and过滤器            filterCombination.AddFilter(andFilter);            //创建管道 根据过滤器来过滤数据集            Pipe p = new Pipe();            List<Goods> filteredGoods = p.Filter(glist, filterCombination);            filteredGoods.ForEach(g =>            {                Console.WriteLine(g.Name + "..." + g.Price + "元");            });


最终结果:

黑人牙膏....16元




0 0