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

一:实际场景介绍

     我们在给用户做订单催付通知的时候,会有这样的一种场景,用户在系统后台设置一组可以催付的规则,比如说订单金额大于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项目的不同功能。如果必…

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…

微软在.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[][…

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

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

Java8面试题

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

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

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

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全球最具价值品牌百强榜》公布…

计算机沙盒应用,既能防木马病毒又能多开应用,这款软件Windows不能没有

各位差友平时在 Windows 电脑上是怎么下载软件的呢&#xff1f;世超猜测很多人会选择在浏览器里直接搜索某个软件的名字&#xff0c;搜索结果中出现官网就从官网下载&#xff0c;没有官网就进到各种资源聚合网站碰碰运气。而众所周知&#xff0c;Windows 平台向来不缺各种流氓软…

从真实项目中抠出来的设计模式——第三篇:责任链模式

一&#xff1a;现实场景 有时候在开发的过程中&#xff0c;我们经常会根据某个状态的值&#xff0c;写出很多的ifelse逻辑&#xff0c;比如拿项目里面的案例来说&#xff0c;如果当前发送的是彩信&#xff0c;此种状态需要如何给实体赋值&#xff0c;如果是短信&#xff0c;邮件…

Spark之Master主备切换机制原理

Spark之Master主备切换机制原理

SQL正在击败NoSQL,这对未来的数据意味着什么

转载自 SQL正在击败NoSQL&#xff0c;这对未来的数据意味着什么 经过多年的沉寂之后&#xff0c;今天的SQL正在复出。缘由如何&#xff1f; 这对数据社区有什么影响&#xff1f; 自从可以利用计算机做事以来&#xff0c;我们一直在收集的数据以指数级的速度在增长&#xff0…

公共计算机课程思政建设实施方案,公共计算机教研组开设课程思政公开课

为了进一步奠定课程思政基础,提高教师将思政元素融入到专业课程的能力,创造一个课程思政的良好氛围,2021年4月30日上午&#xff0c;公共计算机教研组陈雪云老师在文虎楼401教室开设《计算机文化基础(理)》思政课程公开课。授课班级是2020级数学师范1、2班。李美莲、黄婷、龚长斌…

数字奇数和偶数的判断

package lanqiao;/*** 创建人 wdl* 创建时间 2021/4/16* 描述*/ public class TEST {public static void main(String[] args) {int a7,b8;if((a&1)1){System.out.println("a是奇数");}if((b&1)0){System.out.println("b是偶数");}}}

asp.net core源码飘香:从Hosting开始

知识点&#xff1a; 1.Kestrel服务器启动并处理Http请求的过程。 2.Startup的作用。 源码飘香&#xff1a; 总结&#xff1a; asp.net core将web开发拆分为多个独立的组件&#xff0c;大多以http中间件的形式添加到请求管线&#xff0c;也有一下作为基础组件&#xff08;con…