从真实项目中抠出来的设计模式——第二篇:过滤器模式
一:实际场景介绍 我们在给用户做订单催付通知的时候,会有这样的一种场景,用户在系统后台设置一组可以催付的规则,比如说订单金额大于xx元,非黑名单用户,来自哪个地区,已购买过某个商品,指定某个营销活动的人等等这样的条件,如果这时用户在淘宝上下了一个订单,那程序要判断的就是看一下此订单是否满足这些规则中的某一个,如果满足,我们给他发送催付通知,这种场景是很多做CRM的同学都会遇到的问题,那针对这种场景,如何更好的规划业务逻辑呢? 二:普通的编程代码 在这里我们就不考虑多筛选条件下的性能,而只从代码维护复杂度考虑,如果不清楚设计模式的同学,大概会写出如下的代码:1 namespace ConsoleApplication12 {3 class Program4 {5 static void Main(string[] args)6 {7 var regulars = new List<Regulars>();89 regulars.Add(new Regulars() { RegularID = 1, RegularName = "规则1", AnalysisConditons = "xxxx" });10 regulars.Add(new Regulars() { RegularID = 1, RegularName = "规则2", AnalysisConditons = "xxxx" });11 regulars.Add(new Regulars() { RegularID = 1, RegularName = "规则3", AnalysisConditons = "xxxx" });12 regulars.Add(new Regulars() { RegularID = 1, RegularName = "规则4", AnalysisConditons = "xxxx" });13 regulars.Add(new Regulars() { RegularID = 1, RegularName = "规则5", AnalysisConditons = "xxxx" });1415 var filters = FilterRegularID(regulars);16 filters = FilterRegularName(filters);17 filters = FilterCondtions(filters);1819 //... 后续逻辑20 }2122 static List<Regulars> FilterRegularID(List<Regulars> persons)23 {24 //过滤 “姓名” 的逻辑25 return null;26 }2728 static List<Regulars> FilterRegularName(List<Regulars> persons)29 {30 //过滤 “age” 的逻辑31 return null;32 }3334 static List<Regulars> FilterCondtions(List<Regulars> persons)35 {36 //过滤 “email” 的逻辑37 return null;38 }39 }4041 /// <summary>42 /// 各种催付规则43 /// </summary>44 public class Regulars45 {46 public int RegularID { get; set; }4748 public string RegularName { get; set; }4950 public string AnalysisConditons { get; set; }51 }52 } 为了演示,上面的代码是从regularid,regularname,condition三个维度对regulars这个聚合对象进行AND模式的筛选过滤,当过滤维度比较多的时候,这种写法看的出来是简单粗暴,维护起来也必须简单粗暴, 所以上万行代码也就是这么出来的,设计模式告诉我们一个简单的“开闭原则”,那就是追求最小化的修改代码,这种场景有更好的优化策略吗?对应到设计模式上就是“过滤器模式”,专门针对这种场景的解决方案,一个维度一个类,然后通过逻辑运算类将他们进行组合,可以看出这是一种“结构式的设计模式”。 三:过滤器模式 好了,废话不多说,先来看一下优化后的设计图纸如下:从上面这张图纸中可以看到,我已经将三个维度的过滤方法提取成了三个子类,由此抽象出了一个IFilter接口,当然你也可以定义成抽象类,然后实现了两个运算级AND和OR子类Filter,用于动态的对原子性的RegularIDFilter,RegularNameFilter,ReuglarCondtionFilter进行AND,OR逻辑运算,下面我们再看具体代码: 1.IFilterpublic interface IFilter{List<Regulars> Filter(List<Regulars> regulars);} 2. RegularIDFilter1 public class RegularIDFilter : IFilter2 {3 /// <summary>4 /// Regulars的过滤逻辑5 /// </summary>6 /// <param name="regulars"></param>7 /// <returns></returns>8 public List<Regulars> Filter(List<Regulars> regulars)9 {10 return null;11 }12 } 3.RegularNameFilter1 public class RegularNameFilter : IFilter2 {3 /// <summary>4 /// regularName的过滤方式5 /// </summary>6 /// <param name="regulars"></param>7 /// <returns></returns>8 public List<Regulars> Filter(List<Regulars> regulars)9 {10 return null;11 }12 } 4. RegularCondtionFilter1 public class RegularCondtionFilter : IFilter2 {3 /// <summary>4 /// Condition的过滤条件5 /// </summary>6 /// <param name="regulars"></param>7 /// <returns></returns>8 public List<Regulars> Filter(List<Regulars> regulars)9 {10 return null;11 }12 } 5.AndFilter1 /// <summary>2 /// filter的 And 模式3 /// </summary>4 public class AndFilter : IFilter5 {6 List<IFilter> filters = new List<IFilter>();78 public AndFilter(List<IFilter> filters)9 {10 this.filters = filters;11 }1213 public List<Regulars> Filter(List<Regulars> regulars)14 {15 var regularlist = new List<Regulars>(regulars);1617 foreach (var criteriaItem in filters)18 {19 regularlist = criteriaItem.Filter(regularlist);20 }2122 return regularlist;23 }24 } 6.OrFilter1 public class OrFilter : IFilter2 {3 List<IFilter> filters = null;45 public OrFilter(List<IFilter> filters)6 {7 this.filters = filters;8 }910 public List<Regulars> Filter(List<Regulars> regulars)11 {12 //用hash去重13 var resultHash = new HashSet<Regulars>();1415 foreach (var filter in filters)16 {17 var smallPersonList = filter.Filter(regulars);1819 foreach (var small in smallPersonLis