设计模式之过滤器模式

目录

1.简介

2.过滤器的实现

2.1.过滤器的角色

2.2.类图

2.3.具体实现

3.过滤器模式的优点

4.过滤器模式的不足

5.适用的场景


1.简介

过滤器模式(Filter Pattern)或标准模式(Criteria Pattern)是一种结构型设计模式,这种模式允许开发人员使用不同的标准来过滤一组对象,通过逻辑运算以解耦的方式把它们连接起来。说的通俗些就是把一个集合对象根据过滤条件筛选出自己想要的对象。

2.过滤器的实现

2.1.过滤器的角色

抽象过滤器角色(AbstractFilter):负责定义过滤器的实现接口,具体的实现还要具体过滤器角色去参与,客户端可以调用抽象过滤器角色中定义好的方法,将客户端的所有请求委派到具体的实现类去,从而让实现类去处理;
具体过滤器角色(ConcreteFilter):该角色负责具体筛选规则的逻辑实现,最后再返回一个过滤后的数据集合,标准的过滤器只对数据做过滤,当然也可以对集合中的数据做某项处理,再将处理后的集合返回;
被过滤的主体角色(Subject):一个软件系统中可以有一个或多个目标角色,在具体过滤器角色中会对指定感兴趣的目标进行处理,以确保后面的数据确实是我想要的。

2.2.类图

ICriteria : 抽象过滤器角色,定义了抽象接口doFilter

CCriteriaMale: 具体的过滤器角色,过滤male

CCriteriaFemale: 具体的过滤器角色,过滤female

CCriteriaEducation: 具体的过滤器角色,过滤指定学历的

CCriteriaAboveAge: 具体的过滤器角色,过滤大于某个年龄的

CCriteriaAnd:具体的过滤器角色,实现两个具体的过滤器的逻辑与

CCriteriaOr:具体的过滤器角色,实现两个具体的过滤器的逻辑或

CCriteriaAndEx:具体的过滤器角色,实现多个具体的过滤器的逻辑与

CCriteriaOrEx:具体的过滤器角色,实现多个具体的过滤器的逻辑或

CPerson: 被过滤的主体角色

注:里面用到了std::initializer_list,具体用法可参考深入理解可变参数-CSDN博客的第2章节。

2.3.具体实现

主体角色和过滤器代码如下:FilterMode.h

#ifndef _FILTER_MODE_H_
#define _FILTER_MODE_H_
#include <string>
#include <vector>
#include <algorithm>//被过滤的实体类
class CPerson
{
public:explicit CPerson(const std::string& name, const std::string& sex, int age, const std::string& education): m_name(name), m_sex(sex), m_age(age), m_education(education) {}~CPerson() {}public:std::string name() const { return m_name; }std::string sex() const { return m_sex; }int age() const { return m_age; }std::string education() const { return m_education; }std::string toString() const {return std::string("[name:") + m_name + std::string(";sex:") + m_sex + std::string(";age:") + std::to_string(m_age)+ std::string(";education:") + m_education + std::string("]");}private:std::string m_name;std::string m_sex;int         m_age;std::string m_education;
};//抽象过滤器
class ICriteria {
public:virtual std::vector<CPerson*>  doFilter(const std::vector<CPerson*>& persons) = 0;
};//具体过滤器:过滤male
class CCriteriaMale : public ICriteria
{
public:std::vector<CPerson*>  doFilter(const std::vector<CPerson*>& persons) override {std::vector<CPerson*> malePersons;for (auto& it : persons) {if (0 == it->sex().compare("male")) {malePersons.push_back(it);}}return malePersons;}
};//具体过滤器:过滤female
class CCriteriaFemale : public ICriteria
{
public:std::vector<CPerson*>  doFilter(const std::vector<CPerson*>& persons) override {std::vector<CPerson*> femalePersons;for (auto& it : persons) {if (0 == it->sex().compare("female")) {femalePersons.push_back(it);}}return femalePersons;}
};//具体过滤器:过滤学历
class CCriteriaEducation : public ICriteria
{
public:explicit CCriteriaEducation(const std::string& education) :m_education(education) {}
public:std::vector<CPerson*>  doFilter(const std::vector<CPerson*>& persons) override {std::vector<CPerson*> eduPersons;for (auto& it : persons) {if (0 == it->education().compare(m_education)) {eduPersons.push_back(it);}}return eduPersons;}private:std::string m_education;
};//具体过滤器:过滤年龄
class CCriteriaAboveAge : public ICriteria
{
public:explicit CCriteriaAboveAge(int age) : m_age(age) {}public:std::vector<CPerson*>  doFilter(const std::vector<CPerson*>& persons) override {std::vector<CPerson*> agePersons;for (auto& it : persons) {if (it->age() > m_age) {agePersons.push_back(it);}}return agePersons;}
private:int  m_age;
};//具体过滤器:两个过滤器的逻辑与
class CCriteriaAnd : public ICriteria
{
public:explicit CCriteriaAnd(ICriteria* pCriteria1, ICriteria* pCriteria2): m_criteria1(pCriteria1), m_criteria2(pCriteria2) {}public:std::vector<CPerson*>  doFilter(const std::vector<CPerson*>& persons) override {std::vector<CPerson*> andPersons = m_criteria1->doFilter(persons);return m_criteria2->doFilter(andPersons);}
private:ICriteria* m_criteria1;ICriteria* m_criteria2;
};//具体过滤器:1个或多个过滤器的逻辑与
class CCriteriaAndEx : public ICriteria
{
public:explicit CCriteriaAndEx(std::initializer_list<ICriteria*> criteria1s): m_vecCriteria(criteria1s) {}public:std::vector<CPerson*>  doFilter(const std::vector<CPerson*>& persons) override {int index = 0;std::vector<CPerson*> andPersons;for (auto& it : m_vecCriteria) {andPersons = it->doFilter(index == 0 ? persons : andPersons);index++;}return andPersons;}
private:std::vector<ICriteria*> m_vecCriteria;
};//具体过滤器:两个过滤器的逻辑或
class CCriteriaOr : public ICriteria
{
public:explicit CCriteriaOr(ICriteria* pCriteria1, ICriteria* pCriteria2): m_criteria1(pCriteria1), m_criteria2(pCriteria2) {}public:std::vector<CPerson*>  doFilter(const std::vector<CPerson*>& persons) override {std::vector<CPerson*> orPersons = m_criteria1->doFilter(persons);std::vector<CPerson*> orPersons1 = m_criteria2->doFilter(persons);for (auto& it : orPersons1) {if (std::find_if(orPersons.begin(), orPersons.end(),[=](auto& iter) {return it == iter; }) == orPersons.end()) {orPersons.push_back(it);}}return orPersons;}
private:ICriteria* m_criteria1;ICriteria* m_criteria2;
};//CPerson容器包装类
class CPersonContainerWrapper
{
public:CPersonContainerWrapper(std::vector<CPerson*>& vecData): m_vecPesons(vecData) {}
public:CPersonContainerWrapper& operator|(const std::vector<CPerson*>& others) {for (auto& it : others) {if (std::find_if(m_vecPesons.begin(), m_vecPesons.end(),[=](auto& iter) {return it == iter; }) == m_vecPesons.end()) {m_vecPesons.push_back(it);}}return *this;}
private:std::vector<CPerson*>& m_vecPesons;
};//具体过滤器:1个或多个过滤器的逻辑或
class CCriteriaOrEx : public ICriteria
{
public:explicit CCriteriaOrEx(std::initializer_list<ICriteria*> criteria1s): m_vecCriteria(criteria1s) {}public:std::vector<CPerson*>  doFilter(const std::vector<CPerson*>& persons) override {int index = 0;std::vector<CPerson*> orPersons;CPersonContainerWrapper wapper(orPersons);if (m_vecCriteria.size() <= 0) {return persons;}orPersons = m_vecCriteria[0]->doFilter(persons);for (index = 1; index < m_vecCriteria.size(); index++) {wapper | m_vecCriteria[index]->doFilter(persons);}return orPersons;}
private:std::vector<ICriteria*> m_vecCriteria;
};#endif

使用不同的标准(Criteria)和它们的结合来过滤CPerson对象的列表,测试代码如下:

#include "FilterMode.h"
static void printPerson(const std::string& tip, std::vector<CPerson*>& persons) {qDebug() << tip.data();for (auto& it : persons) {qDebug() << it->toString().data();}
}
void main() {std::vector<CPerson*> vecTemp;std::vector<CPerson*> vecPersons;vecPersons.push_back(new CPerson("liu bin", "male", 39, "benke"));vecPersons.push_back(new CPerson("li xiang", "female", 25, "zhuanke"));vecPersons.push_back(new CPerson("he nan shan", "male", 44, "boshi"));vecPersons.push_back(new CPerson("san ling", "female", 56, "suoshi"));vecPersons.push_back(new CPerson("guo dong", "male", 27, "zhuanke"));vecPersons.push_back(new CPerson("jing gang shan", "female", 32, "suoshi"));vecPersons.push_back(new CPerson("shan shan", "female", 41, "benke"));vecPersons.push_back(new CPerson("mei duo", "male", 10, "xiaoxue"));ICriteria* pMaleCriteria = new CCriteriaMale();ICriteria* pFemaleCriteria = new CCriteriaFemale();ICriteria* pAgeCriteria = new CCriteriaAboveAge(26);ICriteria* pEduCriteria = new CCriteriaEducation("benke");ICriteria* pAndCriteria = new CCriteriaAnd(pMaleCriteria, pEduCriteria);ICriteria* pOrCriteria = new CCriteriaOr(pFemaleCriteria, pAgeCriteria);ICriteria* pAndCriteriaEx = new CCriteriaAndEx({ pFemaleCriteria, pAgeCriteria, pEduCriteria });ICriteria* pOrCriteriaEx = new CCriteriaOrEx({ pMaleCriteria, pFemaleCriteria, pEduCriteria,pAgeCriteria });vecTemp = pMaleCriteria->doFilter(vecPersons);printPerson("male: ", vecTemp);vecTemp = pFemaleCriteria->doFilter(vecPersons);printPerson("female: ", vecTemp);vecTemp = pAgeCriteria->doFilter(vecPersons);printPerson("age>26: ", vecTemp);vecTemp = pEduCriteria->doFilter(vecPersons);printPerson("benke: ", vecTemp);vecTemp = pAndCriteria->doFilter(vecPersons);printPerson("benke and male: ", vecTemp);vecTemp = pOrCriteria->doFilter(vecPersons);printPerson("age>26 or female: ", vecTemp);vecTemp = pAndCriteriaEx->doFilter(vecPersons);printPerson("age>26 and benke and female: ", vecTemp);vecTemp = pOrCriteriaEx->doFilter(vecPersons);printPerson("age>26 or benke or male or female: ", vecTemp);for (auto& it : vecTemp) {delete it;}delete pMaleCriteria;delete pFemaleCriteria;delete pAgeCriteria;delete pEduCriteria;delete pAndCriteria;delete pOrCriteria;delete pAndCriteriaEx;delete pOrCriteriaEx;
}

输出:

male: 
[name:liu bin;sex:male;age:39;education:benke]
[name:he nan shan;sex:male;age:44;education:boshi]
[name:guo dong;sex:male;age:27;education:zhuanke]
[name:mei duo;sex:male;age:10;education:xiaoxue]female: 
[name:li xiang;sex:female;age:25;education:zhuanke]
[name:san ling;sex:female;age:56;education:suoshi]
[name:jing gang shan;sex:female;age:32;education:suoshi]
[name:shan shan;sex:female;age:41;education:benke]age>26: 
[name:liu bin;sex:male;age:39;education:benke]
[name:he nan shan;sex:male;age:44;education:boshi]
[name:san ling;sex:female;age:56;education:suoshi]
[name:guo dong;sex:male;age:27;education:zhuanke]
[name:jing gang shan;sex:female;age:32;education:suoshi]
[name:shan shan;sex:female;age:41;education:benke]benke: 
[name:liu bin;sex:male;age:39;education:benke]
[name:shan shan;sex:female;age:41;education:benke]benke and male: 
[name:liu bin;sex:male;age:39;education:benke]age>26 or female: 
[name:li xiang;sex:female;age:25;education:zhuanke]
[name:san ling;sex:female;age:56;education:suoshi]
[name:jing gang shan;sex:female;age:32;education:suoshi]
[name:shan shan;sex:female;age:41;education:benke]
[name:liu bin;sex:male;age:39;education:benke]
[name:he nan shan;sex:male;age:44;education:boshi]
[name:guo dong;sex:male;age:27;education:zhuanke]age>26 and benke and female: 
[name:shan shan;sex:female;age:41;education:benke]age>26 or benke or male or female: 
[name:liu bin;sex:male;age:39;education:benke]
[name:he nan shan;sex:male;age:44;education:boshi]
[name:guo dong;sex:male;age:27;education:zhuanke]
[name:mei duo;sex:male;age:10;education:xiaoxue]
[name:li xiang;sex:female;age:25;education:zhuanke]
[name:san ling;sex:female;age:56;education:suoshi]
[name:jing gang shan;sex:female;age:32;education:suoshi]
[name:shan shan;sex:female;age:41;education:benke]

3.过滤器模式的优点

过滤器模式通过提供一种灵活的方式来处理和筛选对象集合,从而提高代码的灵活性和可维护性。

灵活性过滤器模式充许根据不同的过滤条件对请求进行筛选和传递,这意味看你可以轻松地添加、删除或修改过滤器,而无需修改客户端代码,这使得系统更加灵活,能够适应不同的需求和变化。

可扩展性由于过滤器模式是可扩展的,你可以在不影响现有代码的情况下添加新的过滤器,这有助于降低代码的耦合度,提高模块化程度,使代码更易于维护和扩展。

复用性每个过滤器都可以独立地实现其过滤逻辑,这意味着它们是可复用的,你可以在不同的场景下使用相同的过滤器或者将多个过滤器组合在一起以满足更复杂的过滤需求。

解耦通过将过滤逻辑封装在独立的过滤器中,过滤器模式降低了客户端代码与具体过滤逻辑之间的耦合度,这意味看你可以在不改变客户端代码的情况下更改或替换过滤器,提高了  代码的可维护性。

易于测试由于每个过滤器都是独立的,你可以单独测试每个过滤器,确保它们按照预期工作,这有助于提高代码的可测讨性和可维护性。

简化复杂逻辑通过将复杂的筛选逻辑分解为一系列简单的过滤步骤,过滤器模式可以使代码更易于理解和维护,每个过滤器只关注一个特定的筛选条件,从而使代码更加清晰和模块化。

4.过滤器模式的不足

性能问题当数据集合非常大时,大量的迭代运算,过滤器模式可能会降低程序性能。每次过滤都需要遍历整个数据集合,这可能会降低程序的运行效率。

配置复杂性当需要组合多个过滤器时,可能需要编写大量的配置代码,这可能会增加代码的复杂性。

5.适用的场景

1) 数据筛选

在数据处理中,经常需要对大量的数据进行筛选,以满足特定条件。过滤器设计模式可以将这种需求抽象化,通过定义一个过滤器接口,实现不同的筛选逻辑。这种设计模式可以方便地扩展和修改,满足不同的筛选需求。

2) 请求过滤

在Web应用程序中,通常需要对接收到的请求进行筛选和过滤,例如检查用户身份、过滤目的地址请求等。使用过滤器设计模式,可以将请求的筛选逻辑封装在过滤器中,对每个请求进行处理。这种设计模式可以提高代码的可维护性和可扩展性;在这点上由此可以派生出拦截过滤器模式,需要了解的可以点进去看看,在这里就不过多细说了。

3) 事件过滤

在事件驱动的系统中,经常需要对事件进行筛选和过滤。例如,在事件总线中,可能需要对事件进行分类和筛选,以便将事件分发给不同的消费者。过滤器设计模式可以将这种需求抽象化,通过定义一个一致的过滤器接口,实现不司的事件筛选逻辑。

4) 日志过滤

在日志记录中,通常需要对日志消息进行筛选和过滤,以满定不同的需求。例如,可能需要根据志级别、日志内容等信息进行筛选和过滤。过滤器设计模式可以将这种需求抽象化通过定义一个日志过滤器接口,实现不同的日志筛选逻辑。

5) 数据流过滤

在数据处理流中,经常需要对数据进行筛选和过滤。例如,在流处理中,可能需要对数据进行分类、去重、转换等操作。过滤器设计模式可以将这种需求抽象化,通过定义一个数据流过滤器接口,实现不同的数据筛选逻辑。这种设计模式可以提高数据处理流的灵活性和可抗展性。

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

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

相关文章

【Python学习】Python学习3-变量类型

目录 【Python学习】Python学习3 前言变量赋值多个变量赋值标准数据类型Python Numbers(数字)Python List&#xff08;列表&#xff09;Python Tuple&#xff08;元组&#xff09;Python Dictionary&#xff08;字典&#xff09; Python数据类型转换总结参考 文章所属专区 Py…

【数据库原理】(9)SQL简介

一.SQL 的发展历史 起源&#xff1a;SQL 起源于 1970 年代&#xff0c;由 IBM 的研究员 Edgar F. Codd 提出的关系模型概念演化而来。初期&#xff1a;Boyce 和 Chamberlin 在 IBM 开发了 SQUARE 语言的原型&#xff0c;后发展成为 SQL。这是为了更好地利用和管理关系数据库。…

C#使用条件语句判断用户登录身份

目录 一、示例 二、生成 利用条件语句判断用户登录身份&#xff0c;根据用户登录身份的不同&#xff0c;给予相应的操作权限。 一、示例 主要用if语句及ComboBox控件。其中&#xff0c;ComboBox是窗体中的下拉列表控件&#xff0c;在使用ComboBox控件前&#xff0c;可以先向…

springboot实现ChatGPT式调用(一次调用,持续返回)

下边实现了一个持续返回100以内随机数的接口&#xff0c;在接口超时之前会每隔1秒返回一个随机数 GetMapping(value "/getRandomNum", produces MediaType.TEXT_EVENT_STREAM_VALUE) public SseEmitter getRandomNum() {SseEmitter emitter new SseEmitter();Th…

【airsim】python控制airsim

使用airsim 1.8.1编译完成&#xff0c;进过block项目在cpp测试后&#xff0c;开始踩坑使用python。 使用AirSim\PythonClient\setup.py或者pip安装airsim。 python setup.py install或者 pip install airsim此时&#xff0c;windows电脑的环境信息 (air_py38) D:\code\Gith…

如何计算CAN通信波特率

目录 1、理论 2、实践 3、注意事项 在CAN总线系统中&#xff0c;波特率的计算是一个关键步骤&#xff0c;它确保网络上的所有设备能够以相同的速率进行通信。 1、理论 波特率的计算涉及到几个关键参数&#xff0c;包括CAN控制器的时钟频率、分频因子、以及位时间的不同部分…

vue icon 本地正常 线上打包失败变乱码

出现这个原因是因为sass解析的问题 Node版本高的话可以通过升级sass版本 并且配置vue.config规避这个问题 //给sass配置的东西 这个对应的版本是sass 1.39.0 本人node版本v14 升级sass版本后出现报错css: {loaderOptions: {scss: {additionalData: import "/styles/var…

JVM知识总结(简单且高效)

1. JVM内存与本地内存 JVM内存&#xff1a;受虚拟机内存大小的参数控制&#xff0c;当大小超过参数设置的大小时会报OOM。本地内存&#xff1a;本地内存不受虚拟机内存参数的限制&#xff0c;只受物理内存容量的限制&#xff1b;虽然不受参数的限制&#xff0c;如果所占内存超过…

软件工程概论------文件管理

目录 1.文件的相关概念 2.文件目录 3.位示图 4.索引文件 5.例题 1.文件的相关概念 文件:具有符号名的、在逻辑上具有完整意义的一组相关信息项的集合。 逻辑结构:有结构的记录式文件、无结构的流式文件。 物理结构: 连续结构、链接结构、索引结构、多个物理块的索引表。 …

ROS-arbotix安装

方式一&#xff1a;命令行输入&#xff1a; sudo apt-get install ros-melodic-arbotix如果ROS为其他版本&#xff0c;可将melodic替换为对应版本。 方式二&#xff1a; 先从 github 下载源码&#xff0c;然后调用 catkin_make 编译 git clone https://github.com/vanadiumla…

MySQL--基础篇

这里写目录标题 总览MySQl各个阶段基础篇总览 MySQL概述数据库相关概念查看本机MySQL版本号启停mysql打开windows服务管理windows命令行启停 连接mysql客户端mysql运行逻辑数据模型关系型数据库 总结 SQL总览SQL通用语法SQL语句分类DDL数据库操作表操作查询表创建表结构数据类型…

sublim安装Autoprefixer插件

有时候在写css样式的时候&#xff0c;分不清哪些属性需要前缀&#xff0c;哪些不需要写前缀&#xff0c;sublime text这款编辑器下安装autoprefixer这款插件可以省去很多问题&#xff0c;写起来也很方便。1 确保系统已经安装node.js 可直接去官网上下载并安装&#xff0c;我的系…

c语言:用结构体找出学生年龄|练习题

一、题目 在结构体数组中&#xff0c;输入学生信息&#xff0c;找出学生的年龄。 如图&#xff1a; 二、代码图片【带注释】 三、源代码【带注释】 #include <stdio.h> //设置结构体&#xff0c;结构体有3个变量 struct student { int id; char name[20]; …

BMTrain来高效训练预训练模型-大模型的福音

一.背景知识 在2018年&#xff0c;预训练语言模型技术的出现成为人工智能领域一场革命性的变革。研究表明&#xff0c;通过增加模型参数量和训练数据规模&#xff0c;可以有效提升语言模型的性能&#xff0c;因此十亿、百亿甚至千亿级大模型的探索成为业界的热门话题。这一趋势…

使用Spring Cache优化数据库访问

使用Spring Cache优化数据库访问 在这篇博客中&#xff0c;我们将学习如何使用Spring Cache来优化数据库访问&#xff0c;提高系统性能。我们将创建一个简单的图书管理应用作为示例&#xff0c;并演示如何通过缓存减少对数据库的频繁查询。 1. 项目结构 首先&#xff0c;我们…

使用vite构建Vue3项目

1、安装vite npm init vitelatest npm构建vite项目 yarn create vite yarn构建vite项目2、依次需要配置项目名 、框架选择、原生和ts版本的选择 r enter 重新开始服务 o enter 快速打开浏览器3、项目启动效果

TCP_可靠数据传输原理

引言 在网络通信中&#xff0c;TCP是确保数据可靠传输的关键协议。但在我们深入研究TCP拥塞控制技术之前&#xff0c;让我们先探索可靠数据传输的原理&#xff0c;特别是TCP头部中一些重要字段的作用。 网络层提供了点对点的通信服务&#xff0c;努力交付数据报&#xff0c;但…

Python课程设计基于python的人脸识别佩戴口罩系统设计

wx供重浩&#xff1a;创享日记 对话框发送&#xff1a;python口罩 获取完整论文报告源码源文件 1 研究背景与意义 新型冠状病毒展现出全球化流行和蔓延的趋势&#xff0c;这提醒我们&#xff1a;传染病防治在今后相当长时间内仍是疾病预测控制工作的重点。戴口罩是预防呼吸道…

Qt应用-实现图像截取功能类似QQ上传头像截取功能

本文演示利用Qt实现图像截取功能类似QQ上传头像截取功能。 效果如下,通过移动中间的裁剪区域可以获得一张裁剪后的图片。 目录

UE4运用C++和框架开发坦克大战教程笔记(十四)(第43~45集)

UE4运用C和框架开发坦克大战教程笔记&#xff08;十四&#xff09;&#xff08;第43~45集&#xff09; 43. 单个加载 UObject 功能获取资源 URL 链接实现异步加载单个 UObject 类型资源 44. 批量加载 UObject 功能测试加载单个 UObject 资源批量加载多个同类的 UObject 资源 45…