跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava算法

设计模式实战:过滤器模式(Criteria Pattern)详解

过滤器模式(Criteria Pattern)是一种行为型设计模式,允许使用不同标准过滤一组对象。通过实现 Criteria 接口定义筛选条件,可组合多个标准获得单一标准。示例展示了如何创建 Person 实体类,定义性别与婚姻状态的具体筛选器,并利用 AndCriteria 和 OrCriteria 组合逻辑。这种解耦方式便于灵活扩展新规则,适用于复杂业务场景下的数据过滤需求。

dehua dong发布于 2025/1/17更新于 2026/9/1164 浏览
设计模式实战:过滤器模式(Criteria Pattern)详解

设计模式实战:过滤器模式(Criteria Pattern)详解

在开发中,我们经常需要根据不同的条件从集合中筛选出特定的数据。如果每次都要写一堆 if-else,代码会变得难以维护。过滤器模式(Filter Pattern),也叫标准模式(Criteria Pattern),提供了一种解耦的方式,让我们能用不同的标准来过滤对象,并且可以通过逻辑运算把这些标准组合起来。

核心思路

这个模式的核心在于定义一个 Criteria 接口,所有具体的筛选条件都实现它。这样我们就可以灵活地创建任意数量的筛选类,甚至编写组合筛选类(比如'既是男性又是单身')。最终返回的都是筛选过的数据列表。

代码实现

下面是一个完整的 Java 示例,展示了如何构建这套机制。

1. 定义实体类

首先需要一个被筛选的对象,这里用 Person 代表。包含姓名、性别和婚姻状态。

import java.util.ArrayList;
import java.util.List;

public class Person {
    private String name;
    private String gender;
    private String maritalStatus;

    public Person(String name, String gender, String maritalStatus) {
        this.name = name;
        this.gender = gender;
        this.maritalStatus = maritalStatus;
    }

    @Override
    public String toString() {
        return "Person{name='" + name + "', gender='" + gender + "', maritalStatus='" + maritalStatus + "'}";
    }

    public String getName() { return name; }
    public String getGender() { return gender; }
    public String getMaritalStatus() { return maritalStatus; }
}

2. 定义 Criteria 接口

这是过滤器的契约,接收一组对象,返回满足条件的子集。

interface Criteria {
    List<Person> meetCriteria(List<Person> persons);
}

3. 具体筛选条件

我们可以为性别、婚姻状态分别实现具体的筛选逻辑。注意这里使用了 equalsIgnoreCase 来处理大小写问题。

class CriteriaMale implements Criteria {
    @Override
    public List<Person> meetCriteria(List<Person> persons) {
        List<Person> malePerson = new ArrayList<>();
        for (Person person : persons) {
            if (person.getGender().equalsIgnoreCase("male")) {
                malePerson.add(person);
            }
        }
        return malePerson;
    }
}

class CriteriaFemale implements Criteria {
    @Override
    public List<Person> meetCriteria(List<Person> persons) {
        List<Person> femalePerson = new ArrayList<>();
        for (Person person : persons) {
            if (person.getGender().equalsIgnoreCase("female")) {
                femalePerson.add(person);
            }
        }
        return femalePerson;
    }
}

class CriteriaSingle implements Criteria {
    @Override
    public List<Person> meetCriteria(List<Person> persons) {
        List<Person> filteredList = new ArrayList<>();
        for (Person person : persons) {
            if (person.getMaritalStatus().equalsIgnoreCase("single")) {
                filteredList.add(person);
            }
        }
        return filteredList;
    }
}

4. 组合筛选逻辑

这才是模式的精髓。我们可以把两个标准组合成'且'或'或'的关系。

AndCriteria:需要同时满足两个条件。先应用第一个条件,再对结果应用第二个条件。

class AndCriteria implements Criteria {
    private Criteria criteria;
    private Criteria otherCriteria;

    public AndCriteria(Criteria criteria, Criteria otherCriteria) {
        this.criteria = criteria;
        this.otherCriteria = otherCriteria;
    }

    @Override
    public List<Person> meetCriteria(List<Person> persons) {
        List<Person> firstCriteriaPersons = criteria.meetCriteria(persons);
        return otherCriteria.meetCriteria(firstCriteriaPersons);
    }
}

OrCriteria:满足其中一个就行。分别获取两个条件的结果,然后合并去重。

class OrCriteria implements Criteria {
    private Criteria criteria;
    private Criteria otherCriteria;

    public OrCriteria(Criteria criteria, Criteria otherCriteria) {
        this.criteria = criteria;
        this.otherCriteria = otherCriteria;
    }

    @Override
    public List<Person> meetCriteria(List<Person> persons) {
        List<Person> firstCriteriaPersons = criteria.meetCriteria(persons);
        List<Person> otherCriteriaPersons = otherCriteria.meetCriteria(persons);
        
        // 合并结果,避免重复添加同一个对象实例
        for (Person otherPerson : otherCriteriaPersons) {
            if (!firstCriteriaPersons.contains(otherPerson)) {
                firstCriteriaPersons.add(otherPerson);
            }
        }
        return firstCriteriaPersons;
    }
}

5. 测试运行

最后我们在主方法里组装这些标准并验证结果。可以看到,通过组合 OrCriteria,我们轻松实现了'男性或单身'的复杂查询。

public static void main(String[] args) {
    List<Person> persons = new ArrayList<>();
    persons.add(new Person("Robert", "Male", "Single"));
    persons.add(new Person("John", "Male", "Married"));
    persons.add(new Person("Laura", "Female", "Married"));
    persons.add(new Person("Diana", "Female", "Single"));
    persons.add(new Person("Mike", "Male", "Single"));
    persons.add(new Person("Bobby", "Male", "Single"));

    Criteria male = new CriteriaMale();
    Criteria single = new CriteriaSingle();
    Criteria singleOrMale = new OrCriteria(male, single);

    System.out.println("-----------------");
    System.out.println("All Males:");
    for (Person item : male.meetCriteria(persons)) {
        System.out.println(item);
    }

    System.out.println("-----------------");
    System.out.println("All Singles:");
    for (Person item : single.meetCriteria(persons)) {
        System.out.println(item);
    }

    System.out.println("-----------------");
    System.out.println("Singles OR Males:");
    List<Person> result = singleOrMale.meetCriteria(persons);
    for (Person person : result) {
        System.out.println(person);
    }
}

总结

通过这种方式,我们将筛选逻辑与业务代码分离开来。如果需要新增一种筛选规则,只需实现 Criteria 接口即可,无需修改现有代码。这种开闭原则的应用,让系统在面对需求变更时更加健壮。

目录

  1. 设计模式实战:过滤器模式(Criteria Pattern)详解
  2. 核心思路
  3. 代码实现
  4. 1. 定义实体类
  5. 2. 定义 Criteria 接口
  6. 3. 具体筛选条件
  7. 4. 组合筛选逻辑
  8. 5. 测试运行
  9. 总结

更多推荐文章

查看全部
  • AI Agent Skills 资源合集,支持 Cursor/Claude/Copilot 一键部署
  • 国内环境部署 OpenClaw 个人 AI 助手搭建指南
  • .NET WebApi 项目必要配置项详解
  • LLaMA-Factory 项目介绍与安装部署
  • 前端虚拟列表深度拆解
  • 医疗 AI 中的模型融合与集成策略实战
  • 基于 Zynq FPGA 的雷龙 SD NAND 测试
  • 国产 AI Agent 工具全对比:八大模型部署与使用指南
  • C++ 二叉搜索树基础实现:增删查改详解
  • uv 与 conda 对比:Python 环境管理工具选型指南
  • Python 基础语法入门(一)
  • Python 的十大核心特性详解
  • OpenWebUI联网搜索实战:如何用SearXNG让本地大模型获取实时信息(附百度/360配置)
  • KingbaseES 数据库 MySQL 迁移零改造核心技术与实践
  • Coze 与 DeepSeek 结合实现视频自动化工作流
  • Git-AI:追踪 AI 生成代码的实用工具
  • 洛谷 P10262 亲朋数:C++ 动态规划解法详解
  • Stable Diffusion 模型加载报错排查与修复指南
  • Vue 项目打包优化与多环境部署指南
  • Python 数学可视化:显函数、隐函数及复杂曲线交互绘图

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online