从真实项目中抠出来的设计模式——第二篇:过滤器模式

一:实际场景介绍

     我们在给用户做订单催付通知的时候,会有这样的一种场景,用户在系统后台设置一组可以催付的规则,比如说订单金额大于xx元,非黑名单用户,来自

哪个地区,已购买过某个商品,指定某个营销活动的人等等这样的条件,如果这时用户在淘宝上下了一个订单,那程序要判断的就是看一下此订单是否满足这

些规则中的某一个,如果满足,我们给他发送催付通知,这种场景是很多做CRM的同学都会遇到的问题,那针对这种场景,如何更好的规划业务逻辑呢?

 

二:普通的编程代码 

    在这里我们就不考虑多筛选条件下的性能,而只从代码维护复杂度考虑,如果不清楚设计模式的同学,大概会写出如下的代码:

namespace ConsoleApplication1

{

    class Program

    {

        static void Main(string[] args)

        {

            var regulars = new List<Regulars>();


            regulars.Add(new Regulars() { RegularID = 1, RegularName = "规则1", AnalysisConditons = "xxxx" });

            regulars.Add(new Regulars() { RegularID = 1, RegularName = "规则2", AnalysisConditons = "xxxx" });

            regulars.Add(new Regulars() { RegularID = 1, RegularName = "规则3", AnalysisConditons = "xxxx" });

            regulars.Add(new Regulars() { RegularID = 1, RegularName = "规则4", AnalysisConditons = "xxxx" });

            regulars.Add(new Regulars() { RegularID = 1, RegularName = "规则5", AnalysisConditons = "xxxx" });


            var filters = FilterRegularID(regulars);

            filters = FilterRegularName(filters);

            filters = FilterCondtions(filters);


            //... 后续逻辑

        }


        static List<Regulars> FilterRegularID(List<Regulars> persons)

        {

            //过滤 “姓名” 的逻辑

            return null;

        }


        static List<Regulars> FilterRegularName(List<Regulars> persons)

        {

            //过滤 “age” 的逻辑

            return null;

        }


        static List<Regulars> FilterCondtions(List<Regulars> persons)

        {

            //过滤 “email” 的逻辑

            return null;

        }

    }


    /// <summary>

    /// 各种催付规则

    /// </summary>

    public class Regulars

    {

        public int RegularID { get; set; }


        public string RegularName { get; set; }


        public string AnalysisConditons { get; set; }

    }

}

为了演示,上面的代码是从regularid,regularname,condition三个维度对regulars这个聚合对象进行AND模式的筛选过滤,当过滤维度比较多的时候,这种写法看的出来是简单粗暴,维护起来也必须简单粗暴, 所以上万行代码也就是这么出来的,设计模式告诉我们一个简单的“开闭原则”,那就是追求最小化的修改代码,这种场景有更好的优化策略吗?对应到设计模式上就是“过滤器模式”,专门针对这种场景的解决方案,一个维度一个类,然后通过逻辑运算类将他们进行组合,可以看出这是一种“结构式的设计模式”。

 

三:过滤器模式

   好了,废话不多说,先来看一下优化后的设计图纸如下:

从上面这张图纸中可以看到,我已经将三个维度的过滤方法提取成了三个子类,由此抽象出了一个IFilter接口,当然你也可以定义成抽象类,然后实现了两个运算级AND和OR子类Filter,用于动态的对原子性的RegularIDFilter,RegularNameFilter,ReuglarCondtionFilter进行AND,OR逻辑运算,下面我们再看具体代码:

 

1.IFilter

   public interface IFilter{List<Regulars> Filter(List<Regulars> regulars);}

 

2. RegularIDFilter

public class RegularIDFilter : IFilter

    {

        /// <summary>

        /// Regulars的过滤逻辑

        /// </summary>

        /// <param name="regulars"></param>

        /// <returns></returns>

        public List<Regulars> Filter(List<Regulars> regulars)

        {

            return null;

        }

    }

3.RegularNameFilter

        

public class RegularNameFilter : IFilter

    {

        /// <summary>

        /// regularName的过滤方式

        /// </summary>

        /// <param name="regulars"></param>

        /// <returns></returns>

        public  List<Regulars> Filter(List<Regulars> regulars)

        {

            return null;

        }

    }

4. RegularCondtionFilter

public class RegularCondtionFilter : IFilter

    {

        /// <summary>

        /// Condition的过滤条件

        /// </summary>

        /// <param name="regulars"></param>

        /// <returns></returns>

        public  List<Regulars> Filter(List<Regulars> regulars)

        {

            return null;

        }

    }

5.AndFilter

/// <summary>

    /// filter的 And 模式

    /// </summary>

    public class AndFilter : IFilter

    {

        List<IFilter> filters = new List<IFilter>();


        public AndFilter(List<IFilter> filters)

        {

            this.filters = filters;

        }


        public List<Regulars> Filter(List<Regulars> regulars)

        {

            var regularlist = new List<Regulars>(regulars);


            foreach (var criteriaItem in filters)

            {

                regularlist = criteriaItem.Filter(regularlist);

            }


            return regularlist;

        }

    }


6.OrFilter

public class OrFilter : IFilter

    {

        List<IFilter> filters = null;


        public OrFilter(List<IFilter> filters)

        {

            this.filters = filters;

        }


        public List<Regulars> Filter(List<Regulars> regulars)

        {

            //用hash去重

            var resultHash = new HashSet<Regulars>();


            foreach (var filter in filters)

            {

                var smallPersonList = filter.Filter(regulars);


                foreach (var small in smallPersonList)

                {

                    resultHash.Add(small);

                }

            }


            return resultHash.ToList();

        }

    }

7. 最后我们客户端调用程序就简单了,只要将“原子性”的过滤条件追加到“逻辑运算类”中就完美了,如下图:

当你仔细看完上面的代码,会不会发现,如果后续有需求变更,比如说增加筛选的维度,我只需要新增一个继承IFilter的子类就搞定了,客户端在调用的时候只要

在Filters集合中追加该筛选维度,是不是就OK了,所以这种模式几乎达到了无代码修改的地步~~~好了,本篇就说到了这里,希望对你有帮助~


相关文章;

  • 从真实项目中抠出来的设计模式——第一篇:策略模式

原文地址:http://www.cnblogs.com/huangxincheng/p/6415393.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/326118.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2015蓝桥杯省赛---java---A---8(移动距离)

题目描述 思路分析 行号的差的绝对值列号的差的绝对值 代码实现 package lanqiao;import java.util.Scanner;public class Main {public static void main(String[] args) {int w0,m0,n0;Scanner scanner new Scanner(System.in);wscanner.nextInt();mscanner.nextInt();…

RecyclerView多布局的简单使用

RecyclerView多布局的简单 RecyclerView 是在Android5.0之后推出的&#xff0c;是一个比ListView更加灵活更加高效的适配器类型控件。但是RecyclerView不同于其他类型的适配器&#xff0c;它还需要一个LayoutManager进行页面控制展示。RecyclerView提供了三种布局管理器&#x…

Spring Boot 面试题

转载自 Spring Boot 面试题 问题一 什么是Spring Boot&#xff1f; 多年来&#xff0c;随着新功能的增加&#xff0c;spring变得越来越复杂。只需访问https://spring.io/projects页面&#xff0c;我们就会看到可以在我们的应用程序中使用的所有Spring项目的不同功能。如果必…

可以代表学计算机的标志,桌面上的图标可以用来表示

语音内容&#xff1a;大家好&#xff0c;我是时间财富网智能客服时间君&#xff0c;上述问题将由我为大家进行解答。以计算机为例&#xff0c;桌面上的图标可以用来表示文件、文件夹或快捷方式。“计算机”一般是指“电子计算机”&#xff0c;电子计算机(electronic computer)通…

第四章数据查询基础

第四章数据查询基础 一、查询流程&#xff1a; 1.客户端–》请求一条查询语句–》数据库–》返回查询结果 二、导出数据库脚本&#xff1a; 1.选中数据库–》右击–》任务–》生成脚本–》下一步–》选择存放路径–》高级–》选择架构和数据–》下一步–》确定。 三、查询的语法…

Visual Studio 2017迎来F# 4.1

三月初发布的Visual Studio 2017&#xff0c;包含了F# 4.1和Visual F#工具的更新。F# 4.1带来了语言层面提升以及与C# 7的互操作能力&#xff0c;而那些Visual F#工具是支持Roslyn workspaces的首个版本。 正如上文提到的&#xff0c;F# 4.1带来了语言层面提升以及与C# 7的互操…

Spring 事务原理和使用

转载自 Spring 事务原理和使用 1.SpringTransactional的配置 步骤一、在Spring配置文件中引入命名空间 <beans xmlns"http://www.springframework.org/schema/beans"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xmlns:tx"http://www…

第五章模糊查询和聚合函数

第五章模糊查询和聚合函数 一、模糊查询&#xff1a; 1.关键词&#xff1a;like 2._代表&#xff1a;一个字符&#xff0c;eg:like ‘c’&#xff0c;查询的结果是三个字&#xff0c;中间必须是c 3.%代表&#xff1a;多个字符&#xff0c;eg:like ‘%张’,查询的结果是张结尾的…

Android模拟器之神奇Genymotion的安装

Android模拟器之神奇Genymotion的安装 经常有人问我&#xff0c;Android开发不适用真机的情况下&#xff0c;用什么模拟器比较好用&#xff01;我这里推荐两款&#xff0c;一个是前两年开发时使用的“夜神模拟器”&#xff0c;这个在这就不多说了&#xff01;直接下载安装就可以…

微软在.NET官网上线.NET 架构指南频道

微软在Visual Studio 2017 正式发布的时候也上线了一个参考应用https://github.com/dotnet/eShopOnContainers , 最近微软给这个参考应用写了完善的文档&#xff0c;放在.NET官网的.NET架构频道https://www.microsoft.com/net/architecture。 整个.NET 架构按照4个部分展开&am…

2015蓝桥杯省赛---java---B---10(生命之树)

题目描述 思路分析 dfs无根树变有根树 代码实现 package lanqiao;import java.util.Scanner;public class Main {//提升作用域public static int n;public static int[] w;//每个点的权重public static int[] ww;//每个点作为根节点时能得到的最大权和public static int[][…

第六章连接和分组查询

第六章连接和分组查询 一、分组查询&#xff1a; 1.语法&#xff1a;select 列名 from 表名 where 条件 group by 分组的列 order by 列名 排序方式&#xff08;asc/desc&#xff09; 2.多列分组的语法&#xff1a; select 列名1,列名2 from 表名 where 条件 group by 分组的列…

wps工资表怎么用计算机,wps制作工资表的方法步骤图

wps是一款强大的日常办公软件&#xff0c;我们可以使用wps来制作工资表&#xff0c;想知道具体的操作吗?下面就让学习啦小编告诉你wps如何制作工资表&#xff0c;希望对大家有所帮助。wps制作工资表的方法第一节 建立与使用 WPS表格WPS Office 2007办公 软件中提供了一个名为 …

Java8面试题

转载自 Java8面试题 问题一&#xff1a; Java8支持函数编程是什么意思&#xff1f; 在Java 8之前&#xff0c;所有东西都是面向对象的。除了原语之外&#xff0c;java中的 所有内容都作为对象存在。对方法/函数的所有调用都是使用对象或类引用进行的。 方法/功能本身并不…

Linux中打包和解压到的方法

打包aa为ab.tar.gz tar zcvf ab.tar.gz aa 即可 如果要解压到当前位置 tar zxvf ab.tar.gz 但是如果要解压到其它位置,命令有点不一样的地方,如像要解压到另外的目录,如cc tar zxvf ab.tar.gz -C cc   或者写全路径也行tar zxvf ab.tar.gz -C /home/cc 这样就把这个包的内…

为什么转换到Visual Studio 2017如此 “容易”

与VS 2015相比&#xff0c;Visual Studio 2017在C 功能方面有重大的飞跃。我们希望升级到新版本后能让您的日常工作变得更轻松。 这篇文章主要介绍从Visual Studio 2015升级到2017的步骤。在这个版本中&#xff0c;我们团队使代码库移动到Visual Studio 2017非常容易。这里有四…

jdk的安装与环境变量的配置

jdk安装步骤&#xff1a; 1.双击jdk1.7应用程序进行安装 2.遇到下一步就点&#xff0c;遇到确定也点。最后完成 3.默认安装的路径为&#xff1a;C:\Program Files (x86)\Java\jdk1.7.0_51 4.安装完成之后进行环境变量配置 5.右击计算机&#xff08;此电脑&#xff09; 6.点击属…

2015蓝桥杯省赛---java---A---9(垒筛子)

题目描述 思路分析 递归 会超时 通过30% 代码实现 package lanqiao;import java.util.Scanner;public class Main {public static int op[]new int[7];public static int n,m;public static boolean conflict[][]new boolean[7][7];public static int MOD1000000007;publi…

想进入谷歌吗?先来看看这些面试题吧

转载自 想进入谷歌吗&#xff1f;先来看看这些面试题吧 谷歌&#xff0c;美国的跨国科技企业&#xff0c;致力于互联网搜索、云计算、广告技术等领域&#xff0c;开发并提供大量基于互联网的产品与服务。2016年6月8日&#xff0c;《2016年BrandZ全球最具价值品牌百强榜》公布…