C++过滤器模式详解:实现高效对象筛选

发布时间:2026/9/14 17:30:47
C++过滤器模式详解:实现高效对象筛选 1. 过滤器模式概述在C开发中过滤器模式Filter Pattern是一种非常实用的设计模式它允许我们以解耦的方式对一组对象进行筛选。想象一下你有一个装满各种颜色和形状积木的箱子过滤器模式就像是一个智能的筛子可以帮你快速找出所有红色的积木或者所有圆形的积木甚至是红色且圆形的积木。这种模式的核心价值在于将筛选逻辑从业务代码中解耦出来可以灵活组合多个筛选条件便于扩展新的筛选标准2. C实现过滤器模式的关键组件2.1 基础数据结构定义首先我们需要定义一个基础数据结构作为过滤的目标对象。以人员信息为例class Person { public: Person(std::string name, std::string gender, std::string maritalStatus) : name_(std::move(name)), gender_(std::move(gender)), maritalStatus_(std::move(maritalStatus)) {} std::string getName() const { return name_; } std::string getGender() const { return gender_; } std::string getMaritalStatus() const { return maritalStatus_; } private: std::string name_; std::string gender_; std::string maritalStatus_; };2.2 过滤器接口设计定义过滤器的抽象接口这是整个模式的核心class Criteria { public: virtual ~Criteria() default; virtual std::vectorPerson meetCriteria(const std::vectorPerson persons) 0; };2.3 具体过滤器实现实现几个具体的过滤器// 筛选男性 class CriteriaMale : public Criteria { public: std::vectorPerson meetCriteria(const std::vectorPerson persons) override { std::vectorPerson malePersons; for (const auto person : persons) { if (person.getGender() Male) { malePersons.push_back(person); } } return malePersons; } }; // 筛选女性 class CriteriaFemale : public Criteria { public: std::vectorPerson meetCriteria(const std::vectorPerson persons) override { std::vectorPerson femalePersons; for (const auto person : persons) { if (person.getGender() Female) { femalePersons.push_back(person); } } return femalePersons; } };3. 过滤器组合的高级用法3.1 逻辑与组合过滤器class AndCriteria : public Criteria { public: AndCriteria(std::shared_ptrCriteria criteria, std::shared_ptrCriteria otherCriteria) : criteria_(std::move(criteria)), otherCriteria_(std::move(otherCriteria)) {} std::vectorPerson meetCriteria(const std::vectorPerson persons) override { auto firstCriteriaPersons criteria_-meetCriteria(persons); return otherCriteria_-meetCriteria(firstCriteriaPersons); } private: std::shared_ptrCriteria criteria_; std::shared_ptrCriteria otherCriteria_; };3.2 逻辑或组合过滤器class OrCriteria : public Criteria { public: OrCriteria(std::shared_ptrCriteria criteria, std::shared_ptrCriteria otherCriteria) : criteria_(std::move(criteria)), otherCriteria_(std::move(otherCriteria)) {} std::vectorPerson meetCriteria(const std::vectorPerson persons) override { auto firstCriteriaItems criteria_-meetCriteria(persons); auto otherCriteriaItems otherCriteria_-meetCriteria(persons); // 合并结果并去重 for (const auto person : otherCriteriaItems) { if (std::find(firstCriteriaItems.begin(), firstCriteriaItems.end(), person) firstCriteriaItems.end()) { firstCriteriaItems.push_back(person); } } return firstCriteriaItems; } private: std::shared_ptrCriteria criteria_; std::shared_ptrCriteria otherCriteria_; };4. 实际应用示例4.1 基础使用场景int main() { std::vectorPerson persons { {Robert, Male, Single}, {John, Male, Married}, {Laura, Female, Married}, {Diana, Female, Single}, {Mike, Male, Single}, {Bobby, Male, Single} }; auto male std::make_sharedCriteriaMale(); auto female std::make_sharedCriteriaFemale(); auto single std::make_sharedCriteriaSingle(); // 筛选单身男性 auto singleMale std::make_sharedAndCriteria(single, male); auto singleOrFemale std::make_sharedOrCriteria(single, female); std::cout Males:\n; printPersons(male-meetCriteria(persons)); std::cout \nSingle Males:\n; printPersons(singleMale-meetCriteria(persons)); }4.2 性能优化技巧当处理大量数据时可以考虑以下优化使用移动语义减少拷贝std::vectorPerson meetCriteria(std::vectorPerson persons) { persons.erase(std::remove_if(persons.begin(), persons.end(), [](const Person p) { return p.getGender() ! Male; }), persons.end()); return std::move(persons); }使用并行算法C17及以上std::vectorPerson meetCriteria(const std::vectorPerson persons) { std::vectorPerson result; std::mutex mtx; std::for_each(std::execution::par, persons.begin(), persons.end(), [](const Person p) { if (p.getGender() Male) { std::lock_guardstd::mutex lock(mtx); result.push_back(p); } }); return result; }5. 设计模式对比与选择5.1 与策略模式的区别过滤器模式常被拿来与策略模式比较它们的核心区别在于过滤器模式关注如何筛选对象策略模式关注如何改变对象的行为5.2 与装饰器模式的异同相似点都支持链式调用都可以动态添加功能不同点装饰器模式会修改对象行为过滤器模式只做筛选不改变对象本身6. 实际项目中的应用建议6.1 适用场景电商平台商品筛选日志系统级别过滤数据分析中的条件查询游戏中的单位筛选如选择所有敌方单位6.2 实现注意事项保持过滤器接口简洁考虑使用智能指针管理过滤器生命周期对于复杂条件可以结合lambda表达式auto customFilter [](const std::vectorPerson persons) { std::vectorPerson result; for (const auto p : persons) { if (p.getAge() 18 p.getGender() Female) { result.push_back(p); } } return result; };7. 现代C的改进实现7.1 使用函数对象template typename T class Filter { public: virtual ~Filter() default; virtual bool operator()(const T item) const 0; }; class AgeFilter : public FilterPerson { public: explicit AgeFilter(int minAge) : minAge_(minAge) {} bool operator()(const Person person) const override { return person.getAge() minAge_; } private: int minAge_; };7.2 结合STL算法std::vectorPerson filterPersons(const std::vectorPerson persons, const std::functionbool(const Person) predicate) { std::vectorPerson result; std::copy_if(persons.begin(), persons.end(), std::back_inserter(result), predicate); return result; } // 使用示例 auto adults filterPersons(persons, [](const Person p) { return p.getAge() 18; });8. 测试与调试技巧8.1 单元测试建议为每个过滤器编写测试用例TEST(FilterTest, MaleFilter) { std::vectorPerson testData {{Test, Male, Single}, {Test, Female, Single}}; CriteriaMale filter; auto result filter.meetCriteria(testData); ASSERT_EQ(1, result.size()); EXPECT_EQ(Male, result[0].getGender()); }8.2 常见问题排查空指针问题确保组合过滤器时传入有效的指针性能瓶颈对于大数据集考虑使用更高效的算法条件冲突注意逻辑组合时的优先级问题9. 扩展与变体9.1 支持更复杂的条件class CompositeCriteria : public Criteria { public: void addCriteria(std::shared_ptrCriteria criteria) { criterias_.push_back(std::move(criteria)); } std::vectorPerson meetCriteria(const std::vectorPerson persons) override { std::vectorPerson result persons; for (const auto criteria : criterias_) { result criteria-meetCriteria(result); } return result; } private: std::vectorstd::shared_ptrCriteria criterias_; };9.2 支持动态条件配置class DynamicCriteria : public Criteria { public: using FilterFunc std::functionbool(const Person); explicit DynamicCriteria(FilterFunc func) : func_(std::move(func)) {} std::vectorPerson meetCriteria(const std::vectorPerson persons) override { std::vectorPerson result; std::copy_if(persons.begin(), persons.end(), std::back_inserter(result), func_); return result; } private: FilterFunc func_; }; // 使用示例 auto dynamicFilter std::make_sharedDynamicCriteria([](const Person p) { return p.getAge() 20 p.getGender() Female; });10. 性能考量与最佳实践对于小型数据集简单实现即可对于大型数据集考虑使用并行算法预编译过滤条件使用更高效的数据结构如unordered_set内存管理建议使用智能指针共享过滤器考虑对象池模式重用过滤器实例在多线程环境中确保过滤器是无状态的或者做好线程同步// 线程安全的过滤器实现示例 class ThreadSafeFilter : public Criteria { public: std::vectorPerson meetCriteria(const std::vectorPerson persons) override { std::lock_guardstd::mutex lock(mutex_); // 过滤逻辑 } private: std::mutex mutex_; // 其他成员变量... };

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询