C++中的过滤器模式:原理、实现与应用
在软件开发中,我们经常需要从一组对象中筛选出满足特定条件的子集。例如,电商平台筛选“价格低于200元且评分高于4.5星的商品”,日志系统提取“ERROR级别且包含关键词‘数据库’的日志”,或者社交应用展示“年龄在25-35岁之间的好友”。这类场景的核心需求是**“多条件组合筛选”**,而过滤器模式(Filter Pattern)正是为解决这类问题设计的经典设计模式。
一、过滤器模式的核心概念
过滤器模式(又称筛选器模式)是一种结构型设计模式,它的核心思想是:将对象的过滤逻辑封装在独立的“过滤器”类中,通过组合多个过滤器实现复杂条件的筛选,且筛选逻辑与被筛选对象解耦。
简单来说,过滤器模式就像现实生活中的“筛子”——每个筛子有特定的孔径(过滤条件),多个筛子可以叠放使用(组合条件),最终得到符合所有条件的物品。在代码中,这种思想体现为:
- 被筛选的对象:一组具有共同属性的实体(如商品、用户、日志)。
- 过滤器接口:定义“过滤”行为的规范(如一个
filter方法)。 - 具体过滤器:实现接口的类,封装单一过滤条件(如“价格低于200元”)。
- 组合过滤器:组合多个过滤器,实现逻辑运算(如“且”“或”“非”)。
过滤器模式的优势在于**“单一职责”和“组合灵活”**:每个过滤器只负责一种条件,新增条件只需新增过滤器,且通过组合可快速实现复杂筛选,无需修改原有代码。
二、过滤器模式的结构与UML
过滤器模式的核心结构包含4个部分,其UML类图如下:
+-------------------+ +-------------------+
| Client | | Person |
+-------------------+ +-------------------+
| - main() | | - name: string |
+-------------------+ | - age: int || | - gender: string || | - isMarried: bool || +-------------------+| ^v |
+-------------------+ +-------------------+
| Filter |<------| 具体过滤器 |
+-------------------+ +-------------------+
| + filter(list): | | + filter(list): |
| list<Person> | | list<Person> |
+-------------------+ +-------------------+^|
+-------------------+ +-------------------+
| 组合过滤器 |<------| AndFilter/OrFilter|
+-------------------+ +-------------------+
| - filters: list | | + filter(list): |
| + add(filter) | | list<Person> |
+-------------------+ +-------------------+
- 被筛选对象(如
Person):包含需要被筛选的属性(如年龄、性别),是过滤器的处理目标。 - 过滤器接口(
Filter):定义纯虚方法filter,接收对象集合,返回筛选后的子集。 - 具体过滤器:实现
Filter接口,封装单一条件(如MaleFilter筛选男性,AgeFilter筛选特定年龄范围)。 - 组合过滤器:继承
Filter接口,内部包含多个子过滤器,实现逻辑组合(如AndFilter返回同时满足所有子过滤器的对象,OrFilter返回满足任意子过滤器的对象)。
三、C++实现过滤器模式的实例
下面以“筛选人员信息”为例,完整实现过滤器模式。假设需要筛选“年龄大于30岁的已婚男性”,我们将通过具体过滤器和组合过滤器的配合实现这一需求。
1. 定义被筛选对象(Person类)
首先定义需要被筛选的对象Person,包含姓名、年龄、性别、婚姻状态等属性:
#include <string>
#include <vector>
#include <memory> // 智能指针,用于管理过滤器生命周期// 被筛选的对象:人员信息
class Person {
private:std::string name; // 姓名int age; // 年龄std::string gender; // 性别("Male"/"Female")bool isMarried; // 是否已婚public:// 构造函数Person(std::string name, int age, std::string gender, bool isMarried): name(std::move(name)), age(age), gender(std::move(gender)), isMarried(isMarried) {}// getter方法(供过滤器访问属性)std::string getName() const { return name; }int getAge() const { return age; }std::string getGender() const { return gender; }bool getIsMarried() const { return isMarried; }
};
2. 定义过滤器接口(Filter)
过滤器接口是所有过滤器的基类,定义filter方法作为筛选行为的规范:
// 过滤器接口
class Filter {
public:// 纯虚方法:筛选人员集合,返回符合条件的子集virtual std::vector<Person> filter(const std::vector<Person>& persons) const = 0;// 虚析构函数(确保子类析构正常)virtual ~Filter() = default;
};
3. 实现具体过滤器
具体过滤器继承Filter接口,实现单一筛选条件。这里我们实现3个常用过滤器:
(1)筛选男性:MaleFilter
// 筛选男性的过滤器
