使用过滤器模式,让客户关怀中的代码更加干净整洁

一:实际场景介绍

我们在给用户做订单催付通知的时候,会有这样的一种场景,用户在系统后台设置一组可以催付的规则,比如说订单金额大于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. 最后我们客户端调用程序就简单了,只要将“原子性”的过滤条件追加到“逻辑运算类”中就完美了,如下图:


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" });//追加filter条件var filterList = new IFilter[3] {new RegularIDFilter(),new RegularNameFilter(),new RegularCondtionFilter()};var andCriteria = new AndFilter(filterList.ToList());//进行 And组合 过滤andCriteria.Filter(regulars);}}

当你仔细看完上面的代码,会不会发现,如果后续有需求变更,比如说增加筛选的维度,我只需要新增一个继承 IFilter 的子类就搞定了,客户端在调用的时候只要在Filters集合中追加该筛选维度,是不是就OK了,所以这种模式几乎达到了无代码修改的地步~~~好了,本篇就说到了这里,希望对你有帮助~

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

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

相关文章

C++实现各种排序以及复杂度,稳定性分析

代码如下: #include<iostream> using namespace std;void Bubble_Sort(int *a, int n) {bool flag;int tmp 0;for (int i n - 1; i > 0; i--){flag false;for (int j 0; j < i; j){if (a[j] > a[j 1]){swap(a[j], a[j 1]);flag true;}}if (!flag) break…

Webapi管理和性能测试工具WebBenchmark

WebBenchmark是一款基于开源通讯组件Beetlex扩展的Webapi管理和性能测试工具&#xff0c;在传统工具中一般管理工具缺乏性能压测能力或有性能压测的缺少管理功能&#xff1b;WebBenchmark的设计目标是就管理和性能测试能力同时具备。接下来介绍一下工具的功能和使用&#xff1a…

Abstract Factory(抽象工厂)--对象创建模式

Abstract Factory &#xff08;抽象工厂&#xff09;–对象创建模式 一、意图 提供一个创建一系列相关或者相互依赖的接口&#xff0c;而无需指定它们具体的类。 二、动机 1.在软件系统中&#xff0c;经常面临着“一系列相互依赖的对象”的创建工 作;同时&#xff0c;由于需求…

Builder(生成器)--对象创建型模式

Builder&#xff08;生成器&#xff09;–对象创建型模式 一、意图 将一个复杂的对象构建与它的表示分离&#xff0c;使得同样的构建过程可以创建不同的表示。 二、动机 1.在软件系统中&#xff0c;有时候面临着“一个复杂对象”的创建工作&#xff0c;其通常由各个部分的子对…

Gartner:缺乏技术人才将影响企业数字化转型

导语大多数公司在数字化转型的阶段对所需的技能方面都处于“盲目”状态。正文随着COVID-19响应加快了数字化转型的速度和规模&#xff0c;缺乏数字化技能可能会危害人才计划不统一的公司。甚至在冠状病毒大流行之前&#xff0c;董事会就将数字/技术中断列为2020年的头等大事&am…

DEBUG org.springframework.web.servlet.DispatcherServlet - Error rendering view [org.thymeleaf.spring

报错信息如下: 报错原因: thymeleaf有一些限制&#xff0c;使用th语言&#xff0c;内容为空就会报错 改成这样解决问题:

Factory Method(工厂方法)--对象创建型模式

Factory Method&#xff08;工厂方法&#xff09;–对象创建型模式 一、意图 定义一个用于创建对象的接口&#xff0c;让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到其子类。 二、动机 1.在软件系统中&#xff0c;经常面临着创建对象的工作;由于需求的变化…

全内存的redis用习惯了?那能突破内存限制类redis产品ssdb呢?

首先说一下背景&#xff0c;在双十一的时候&#xff0c;我们系统接受X宝的订单推送&#xff0c;原先的实现方式是使用 redis 的 List 作为推送数据的承载&#xff0c;在非大促的场景下&#xff0c;一切运行正常&#xff0c;内存占用大概3-4G&#xff0c;机器是16G内存。由于提前…

Prototype(原型)--对象创建模式

Prototype&#xff08;原型&#xff09;–对象创建模式 一、意图 用原型实例指定创建对象的种类&#xff0c;并且通过拷贝这些原型创建新的对象。 二、动机 1.在软件系统中&#xff0c;经常面临着“某些结构复杂的对象”的创建工作&#xff1b;由于需求的变化&#xff0c;这些…

认证授权方案之授权揭秘 (上篇)

一、前言回顾&#xff1a;认证授权方案之授权初识从上一节中&#xff0c;我们在对授权系统已经有了初步的认识和使用&#xff0c;可以发现&#xff0c;asp.net core为我们提供的授权策略是一个非常强大丰富且灵活的认证授权方案&#xff0c;能够满足大部分的授权场景。在Config…

Singleton(单件)--对象创建模式

Singleton&#xff08;单件&#xff09;–对象创建模式 一、意图 保证一个类仅有一个实例&#xff0c;并提供一个访问它的全局访问点。 二、动机 1.在软件系统中&#xff0c;经常有这样一些特殊的类&#xff0c;必须保证它们在系统中只存在一个实例&#xff0c;才能确保它们的…

龙芯团队 在移值 MIPS64 下的.NET Core 进度速报

写在开始前我们的主要业务基于 dotnet core 2.x 与 3.1 完成&#xff0c;目前 dotnet core 3.1 支持的 CPU 架构列表中还不包含龙芯&#xff0c;且在 gitlab issue 中表示官方当前没有对 MIPS 的支持计划。更具体操作系统与 CPU 架构列表见 [Download .NET Core 3.1](https://d…

Adapter(适配器)--类对象结构型模式

Adapter&#xff08;适配器&#xff09;–类对象结构型模式 一、意图 将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本接口不兼容而不能一起工作的那些类可以一起工作。 二、动机 1.在软件系统中&#xff0c;由于应用环境的变化&#xff0c;常常需要将“一…

如何使用ABP框架(2)三层架构与领域驱动设计的对比

本文来自长沙.NET技术社区&#xff0c;原创&#xff1a;邹溪源。全文共有8500字&#xff0c;读完需耗时10分钟。题图来自pixabay简述上一篇简述了ABP框架中的一些基础理论&#xff0c;包括ABP前后端项目的分层结构&#xff0c;以及后端项目中涉及到的知识点&#xff0c;例如DTO…

Bridge(桥接)--对象结构模式

Bridge&#xff08;桥接&#xff09;–对象结构模式 一、意图 将抽象部分与它的实现部分分离&#xff0c;使它们都可以独立的变化。 二、动机 1.由于某些类型的固有的实现逻辑&#xff0c;使得它们具有两个变化的维度&#xff0c;乃至多个纬度的变化。 2.如何应对这种“多维度…

Composite(组合)--对象结构型模式

Composite&#xff08;组合&#xff09;–对象结构型模式 一、意图 将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。 二、动机 1.软件在某些情况下&#xff0c;客户代码过多的依赖于对象容器复杂的内部实现结构…

[SpringBoot2]ajax函数中data参数的数据设置方式

ajax函数中data参数的数据设置方式&#xff1a;

Blazor带我重玩前端(二)

概览Blazor目前有两种托管模式&#xff0c;一种是Server-Side模式&#xff0c;一种是WebAssembly模式。官方首先支持的是Service-Side模式&#xff0c;使用WebAssembly模式&#xff0c;需要更新到最新版VS2019。小编目前的精力是更多的专注于Blazor-WebAssembly模式的研究&…

Decorator(装饰)--对象结构型模式

Decorator&#xff08;装饰&#xff09;–对象结构型模式 一、意图 1.动态地给一个对象添加一些额外的职责。就增加功能来说&#xff0c;Decorator模式相比生成子类更为灵活。 二、动机 1.在某些情况下我们可能会“过度地使用继承来扩展对象的功能”&#xff0c; 由于继承为类…

Facade(外观)--对象结构型模式

Facade&#xff08;外观&#xff09;–对象结构型模式 一、意图 为子系统中的一组接口提供一个一致的界面&#xff0c;Facade模式定义了一个高层接口&#xff0c;这个接口使得这一子系统更加容易使用。 二、动机 1.上述左边方案的问题在于组件的客户和组件中各种复杂的子系…