作者:逆境不可逃

希望大家能多多关注点赞收藏一键三连!!!

你的支持是我创作的动力!!!


一、过滤器模式核心概念

过滤器模式(也叫标准模式 / Criteria Pattern)是一种行为型设计模式,核心思想是:

  • 定义多个「过滤规则(过滤器)」,可以单独使用组合使用(与 / 或 / 非);
  • 对一组对象进行筛选,最终得到符合条件的对象集合;
  • 优点:规则解耦(新增 / 修改过滤规则不影响原有代码)、规则可复用、支持灵活组合。

简单理解:你网购时筛选商品 ——“价格 < 500 元”“包邮”“好评率 > 95%”,每个条件就是一个过滤器,组合起来就是过滤器模式的典型应用。

二、核心结构

过滤器模式通常包含 4 个核心角色:

  1. 目标对象(Entity):被过滤的对象(如商品、用户、订单);
  2. 过滤器接口(Filter/Criteria):定义过滤方法(如 List<T> filter(List<T> list));
  3. 具体过滤器(ConcreteFilter):实现接口,定义具体的过滤规则;
  4. 组合过滤器(CompositeFilter):组合多个过滤器(如 “与 / 或” 逻辑)。

三、实际场景:电商商品筛选

场景描述

假设你开发一个电商系统,需要实现商品筛选功能:

  • 筛选条件:价格区间、是否包邮、是否为新品(上架时间 < 7 天);
  • 支持组合筛选(如 “价格 < 500 元 且 包邮”“新品 或 包邮”)
步骤 1:定义目标对象(商品)
import java.time.LocalDateTime;

// 商品实体(被过滤的对象)
public class Product {
    private String name;       // 商品名称
    private double price;      // 价格
    private boolean freeShip;  // 是否包邮
    private LocalDateTime createTime; // 上架时间

    // 构造器、getter/setter(省略,实际开发需补充)
    public Product(String name, double price, boolean freeShip, LocalDateTime createTime) {
        this.name = name;
        this.price = price;
        this.freeShip = freeShip;
        this.createTime = createTime;
    }

    // 重写toString,方便打印结果
    @Override
    public String toString() {
        return "Product{" +
                "name='" + name + '\'' +
                ", price=" + price +
                ", freeShip=" + freeShip +
                ", createTime=" + createTime +
                '}';
    }

    // getter方法(必须,过滤器需要读取属性)
    public double getPrice() { return price; }
    public boolean isFreeShip() { return freeShip; }
    public LocalDateTime getCreateTime() { return createTime; }
    public String getName() { return name; }
}
步骤 2:定义过滤器接口
import java.util.List;

// 过滤器接口:定义统一的过滤方法
public interface ProductFilter {
    // 入参:待过滤的商品列表;返回值:符合条件的商品列表
    List<Product> filter(List<Product> products);
}
步骤 3:实现具体过滤器(单一规则)
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

// 过滤器1:价格过滤(价格<指定值)
public class PriceFilter implements ProductFilter {
    private double maxPrice; // 最大价格阈值

    public PriceFilter(double maxPrice) {
        this.maxPrice = maxPrice;
    }

    @Override
    public List<Product> filter(List<Product> products) {
        // 过滤逻辑:价格 < maxPrice
        return products.stream()
                .filter(p -> p.getPrice() < maxPrice)
                .collect(Collectors.toList());
    }
}

// 过滤器2:包邮过滤
public class FreeShipFilter implements ProductFilter {
    @Override
    public List<Product> filter(List<Product> products) {
        // 过滤逻辑:包邮(freeShip=true)
        return products.stream()
                .filter(Product::isFreeShip)
                .collect(Collectors.toList());
    }
}

// 过滤器3:新品过滤(上架时间<7天)
public class NewProductFilter implements ProductFilter {
    @Override
    public List<Product> filter(List<Product> products) {
        LocalDateTime sevenDaysAgo = LocalDateTime.now().minusDays(7);
        // 过滤逻辑:上架时间 > 7天前(即近7天上架)
        return products.stream()
                .filter(p -> p.getCreateTime().isAfter(sevenDaysAgo))
                .collect(Collectors.toList());
    }
}
步骤 4:实现组合过滤器(多规则组合)
import java.util.List;
import java.util.stream.Collectors;

// 组合过滤器:实现“与”逻辑(同时满足多个过滤器)
public class AndFilter implements ProductFilter {
    private ProductFilter[] filters; // 待组合的过滤器数组

    public AndFilter(ProductFilter... filters) {
        this.filters = filters;
    }

    @Override
    public List<Product> filter(List<Product> products) {
        List<Product> result = products;
        // 依次应用所有过滤器(只有同时满足所有规则才会保留)
        for (ProductFilter filter : filters) {
            result = filter.filter(result);
            if (result.isEmpty()) break; // 无数据时提前终止
        }
        return result;
    }
}

// 组合过滤器:实现“或”逻辑(满足任意一个过滤器)
public class OrFilter implements ProductFilter {
    private ProductFilter[] filters;

    public OrFilter(ProductFilter... filters) {
        this.filters = filters;
    }

    @Override
    public List<Product> filter(List<Product> products) {
        // 只要商品满足任意一个过滤器的条件,就保留
        return products.stream()
                .filter(product -> {
                    for (ProductFilter filter : filters) {
                        // 检查当前商品是否符合某个过滤器的条件
                        List<Product> filtered = filter.filter(List.of(product));
                        if (!filtered.isEmpty()) {
                            return true;
                        }
                    }
                    return false;
                })
                .collect(Collectors.toList());
    }
}

// 扩展:非过滤器(取反逻辑)
public class NotFilter implements ProductFilter {
    private ProductFilter filter;

    public NotFilter(ProductFilter filter) {
        this.filter = filter;
    }

    @Override
    public List<Product> filter(List<Product> products) {
        // 先获取符合条件的商品,再取反
        List<Product> matched = filter.filter(products);
        return products.stream()
                .filter(p -> !matched.contains(p))
                .collect(Collectors.toList());
    }
}

五、测试用代码

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

public class FilterPatternTest {
    public static void main(String[] args) {
        // 1. 准备测试数据:创建5个商品
        List<Product> productList = new ArrayList<>();
        productList.add(new Product("手机", 4999.0, false, LocalDateTime.now().minusDays(2))); // 新品、不包邮、高价
        productList.add(new Product("耳机", 299.0, true, LocalDateTime.now().minusDays(10))); // 包邮、非新品、低价
        productList.add(new Product("充电宝", 89.0, true, LocalDateTime.now().minusDays(3))); // 包邮、新品、低价
        productList.add(new Product("键盘", 399.0, false, LocalDateTime.now().minusDays(1))); // 新品、不包邮、低价
        productList.add(new Product("鼠标", 199.0, false, LocalDateTime.now().minusDays(15))); // 非新品、不包邮、低价

        // 2. 定义单个过滤器
        ProductFilter priceFilter = new PriceFilter(500.0); // 价格<500元
        ProductFilter freeShipFilter = new FreeShipFilter(); // 包邮
        ProductFilter newProductFilter = new NewProductFilter(); // 新品

        // 3. 测试单个过滤规则
        System.out.println("===== 价格<500元的商品 =====");
        priceFilter.filter(productList).forEach(System.out::println);

        // 4. 测试组合过滤:价格<500元 且 包邮
        System.out.println("\n===== 价格<500元 且 包邮的商品 =====");
        ProductFilter andFilter = new AndFilter(priceFilter, freeShipFilter);
        andFilter.filter(productList).forEach(System.out::println);

        // 5. 测试组合过滤:新品 或 包邮
        System.out.println("\n===== 新品 或 包邮的商品 =====");
        ProductFilter orFilter = new OrFilter(newProductFilter, freeShipFilter);
        orFilter.filter(productList).forEach(System.out::println);

        // 6. 测试非过滤:不包邮的商品
        System.out.println("\n===== 不包邮的商品 =====");
        ProductFilter notFilter = new NotFilter(freeShipFilter);
        notFilter.filter(productList).forEach(System.out::println);
    }
}

六、测试输出结果

===== 价格<500元的商品 =====
Product{name='耳机', price=299.0, freeShip=true, createTime=2026-02-14T10:00:00}
Product{name='充电宝', price=89.0, freeShip=true, createTime=2026-02-21T10:00:00}
Product{name='键盘', price=399.0, freeShip=false, createTime=2026-02-23T10:00:00}
Product{name='鼠标', price=199.0, freeShip=false, createTime=2026-02-09T10:00:00}

===== 价格<500元 且 包邮的商品 =====
Product{name='耳机', price=299.0, freeShip=true, createTime=2026-02-14T10:00:00}
Product{name='充电宝', price=89.0, freeShip=true, createTime=2026-02-21T10:00:00}

===== 新品 或 包邮的商品 =====
Product{name='手机', price=4999.0, freeShip=false, createTime=2026-02-22T10:00:00}
Product{name='耳机', price=299.0, freeShip=true, createTime=2026-02-14T10:00:00}
Product{name='充电宝', price=89.0, freeShip=true, createTime=2026-02-21T10:00:00}
Product{name='键盘', price=399.0, freeShip=false, createTime=2026-02-23T10:00:00}

===== 不包邮的商品 =====
Product{name='手机', price=4999.0, freeShip=false, createTime=2026-02-22T10:00:00}
Product{name='键盘', price=399.0, freeShip=false, createTime=2026-02-23T10:00:00}
Product{name='鼠标', price=199.0, freeShip=false, createTime=2026-02-09T10:00:00}

七、实际应用扩展建议

  1. 性能优化
    • 若数据量较大,可将 Stream 替换为普通循环(减少流式 API 的开销);
    • 对高频过滤条件,可提前缓存过滤结果(如缓存 “包邮商品列表”)。
  2. 规则扩展
    • 新增过滤规则时,只需实现 ProductFilter 接口(如 BrandFilter 按品牌过滤、ScoreFilter 按好评率过滤),无需修改原有代码,符合「开闭原则」;
    • 支持更复杂的组合(如 AndFilter(OrFilter(a,b), c) → “(a 或 b) 且 c”)。
  3. 实际业务场景
    • 后台管理系统的 “用户筛选”(按角色、注册时间、活跃度);
    • 日志系统的 “日志过滤”(按级别、模块、时间);
    • 订单系统的 “订单筛选”(按状态、金额、支付方式)。

总结

  1. 过滤器模式的核心是将过滤规则抽象为独立组件,实现规则与业务逻辑解耦;
  2. 通过「单一过滤器 + 组合过滤器」,可灵活实现任意复杂的筛选逻辑,且新增规则成本极低;
  3. 在 Java 中结合 Stream API 能简化过滤代码,适合电商、后台管理等需要多条件筛选的场景。

扩展

扩展 1:动态配置过滤规则(前端传参场景)

实际开发中,过滤条件往往由前端用户选择(如价格区间、是否包邮、新品等),需要动态组装过滤器,而非硬编码。

步骤 1:定义过滤条件 DTO(接收前端参数)
import java.time.LocalDateTime;

// 前端传入的过滤条件封装类
public class ProductFilterDTO {
    private Double minPrice;    // 最低价格(可选)
    private Double maxPrice;    // 最高价格(可选)
    private Boolean freeShip;   // 是否包邮(可选,null表示不筛选)
    private Boolean isNew;      // 是否新品(可选,null表示不筛选)

    // 构造器、getter/setter
    public ProductFilterDTO(Double minPrice, Double maxPrice, Boolean freeShip, Boolean isNew) {
        this.minPrice = minPrice;
        this.maxPrice = maxPrice;
        this.freeShip = freeShip;
        this.isNew = isNew;
    }

    // getter方法
    public Double getMinPrice() { return minPrice; }
    public Double getMaxPrice() { return maxPrice; }
    public Boolean getFreeShip() { return freeShip; }
    public Boolean getIsNew() { return isNew; }
}
步骤 2:实现动态过滤器组装工具类
import java.util.ArrayList;
import java.util.List;

// 动态组装过滤器的工具类
public class FilterAssembler {
    /**
     * 根据前端DTO动态组装过滤器(只组装非空的过滤条件)
     */
    public static ProductFilter assembleFilter(ProductFilterDTO dto) {
        List<ProductFilter> filterList = new ArrayList<>();

        // 1. 价格过滤(支持区间:minPrice <= 价格 <= maxPrice)
        if (dto.getMinPrice() != null || dto.getMaxPrice() != null) {
            filterList.add(new PriceRangeFilter(dto.getMinPrice(), dto.getMaxPrice()));
        }

        // 2. 包邮过滤(仅当freeShip不为null时添加)
        if (dto.getFreeShip() != null) {
            filterList.add(new FreeShipFilter(dto.getFreeShip()));
        }

        // 3. 新品过滤(仅当isNew不为null时添加)
        if (dto.getIsNew() != null) {
            filterList.add(new NewProductFilter(dto.getIsNew()));
        }

        // 无过滤条件时,返回“全部通过”的过滤器
        if (filterList.isEmpty()) {
            return products -> products;
        }

        // 多个条件默认按“与”逻辑组合(同时满足)
        return new AndFilter(filterList.toArray(new ProductFilter[0]));
    }

    // 扩展:价格区间过滤器(替代原单一价格过滤器)
    static class PriceRangeFilter implements ProductFilter {
        private Double minPrice;
        private Double maxPrice;

        public PriceRangeFilter(Double minPrice, Double maxPrice) {
            this.minPrice = minPrice;
            this.maxPrice = maxPrice;
        }

        @Override
        public List<Product> filter(List<Product> products) {
            return products.stream()
                    .filter(p -> {
                        boolean minOk = (minPrice == null) || p.getPrice() >= minPrice;
                        boolean maxOk = (maxPrice == null) || p.getPrice() <= maxPrice;
                        return minOk && maxOk;
                    })
                    .collect(Collectors.toList());
        }
    }

    // 扩展:可配置的包邮过滤器(支持“包邮/不包邮”)
    static class FreeShipFilter implements ProductFilter {
        private boolean expectFreeShip;

        public FreeShipFilter(boolean expectFreeShip) {
            this.expectFreeShip = expectFreeShip;
        }

        @Override
        public List<Product> filter(List<Product> products) {
            return products.stream()
                    .filter(p -> p.isFreeShip() == expectFreeShip)
                    .collect(Collectors.toList());
        }
    }

    // 扩展:可配置的新品过滤器(支持“是新品/不是新品”)
    static class NewProductFilter implements ProductFilter {
        private boolean expectNew;

        public NewProductFilter(boolean expectNew) {
            this.expectNew = expectNew;
        }

        @Override
        public List<Product> filter(List<Product> products) {
            LocalDateTime sevenDaysAgo = LocalDateTime.now().minusDays(7);
            return products.stream()
                    .filter(p -> {
                        boolean isNew = p.getCreateTime().isAfter(sevenDaysAgo);
                        return isNew == expectNew;
                    })
                    .collect(Collectors.toList());
        }
    }
}
步骤 3:测试动态组装过滤器
public class DynamicFilterTest {
    public static void main(String[] args) {
        // 1. 复用之前的商品列表(productList)
        List<Product> productList = initProductList();

        // 2. 模拟前端传入的条件:价格100-400元 且 包邮
        ProductFilterDTO dto = new ProductFilterDTO(100.0, 400.0, true, null);
        ProductFilter dynamicFilter = FilterAssembler.assembleFilter(dto);

        // 3. 执行过滤
        System.out.println("===== 动态筛选:价格100-400元 且 包邮 =====");
        dynamicFilter.filter(productList).forEach(System.out::println);

        // 4. 模拟前端传入的条件:非新品 且 不包邮
        ProductFilterDTO dto2 = new ProductFilterDTO(null, null, false, false);
        ProductFilter dynamicFilter2 = FilterAssembler.assembleFilter(dto2);
        System.out.println("\n===== 动态筛选:非新品 且 不包邮 =====");
        dynamicFilter2.filter(productList).forEach(System.out::println);
    }

    // 初始化商品列表(复用之前的测试数据)
    private static List<Product> initProductList() {
        List<Product> productList = new ArrayList<>();
        productList.add(new Product("手机", 4999.0, false, LocalDateTime.now().minusDays(2)));
        productList.add(new Product("耳机", 299.0, true, LocalDateTime.now().minusDays(10)));
        productList.add(new Product("充电宝", 89.0, true, LocalDateTime.now().minusDays(3)));
        productList.add(new Product("键盘", 399.0, false, LocalDateTime.now().minusDays(1)));
        productList.add(new Product("鼠标", 199.0, false, LocalDateTime.now().minusDays(15)));
        return productList;
    }
}
输出结果
===== 动态筛选:价格100-400元 且 包邮 =====
Product{name='耳机', price=299.0, freeShip=true, createTime=2026-02-14T10:00:00}

===== 动态筛选:非新品 且 不包邮 =====
Product{name='鼠标', price=199.0, freeShip=false, createTime=2026-02-09T10:00:00}

扩展 2:高性能批量过滤(大数据量场景)

当商品列表数据量达到万级 / 十万级时,Stream API 的开销会增大,需优化为普通循环 + 提前终止 + 并行处理

高性能过滤器实现
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.TimeUnit;

// 高性能批量过滤器(适配大数据量)
public class HighPerformanceFilter implements ProductFilter {
    private ProductFilter[] filters;
    // 并行处理的线程池(复用JDK默认的ForkJoinPool)
    private static final ForkJoinPool POOL = new ForkJoinPool(Runtime.getRuntime().availableProcessors());

    public HighPerformanceFilter(ProductFilter... filters) {
        this.filters = filters;
    }

    @Override
    public List<Product> filter(List<Product> products) {
        List<Product> result = new ArrayList<>(products.size());

        // 1. 大数据量时启用并行处理(阈值可根据业务调整,这里设为1000)
        if (products.size() > 1000) {
            POOL.submit(() -> {
                products.parallelStream().forEach(product -> {
                    if (matchAllFilters(product)) {
                        synchronized (result) { // 线程安全添加
                            result.add(product);
                        }
                    }
                });
            }).join();
        } else {
            // 2. 小数据量用普通循环(减少并行开销)
            for (Product product : products) {
                if (matchAllFilters(product)) {
                    result.add(product);
                }
            }
        }
        return result;
    }

    /**
     * 检查商品是否匹配所有过滤器(提前终止:只要一个不匹配就返回false)
     */
    private boolean matchAllFilters(Product product) {
        for (ProductFilter filter : filters) {
            // 单个商品过滤,避免创建List,提升性能
            if (!filter.filter(List.of(product)).isEmpty()) {
                continue;
            }
            return false; // 不匹配,提前终止
        }
        return true;
    }

    // 测试高性能过滤
    public static void main(String[] args) {
        // 1. 构造10000个测试商品(模拟大数据量)
        List<Product> bigProductList = new ArrayList<>(10000);
        LocalDateTime now = LocalDateTime.now();
        for (int i = 0; i < 10000; i++) {
            bigProductList.add(new Product(
                    "商品" + i,
                    100 + i % 500, // 价格100-600
                    i % 3 == 0,    // 每3个商品一个包邮
                    now.minusDays(i % 10) // 上架时间0-9天前
            ));
        }

        // 2. 定义过滤条件:价格<500 且 包邮 且 新品
        ProductFilter priceFilter = new FilterAssembler.PriceRangeFilter(null, 500.0);
        ProductFilter freeShipFilter = new FilterAssembler.FreeShipFilter(true);
        ProductFilter newFilter = new FilterAssembler.NewProductFilter(true);

        // 3. 高性能过滤
        HighPerformanceFilter highPerfFilter = new HighPerformanceFilter(priceFilter, freeShipFilter, newFilter);
        long start = System.currentTimeMillis();
        List<Product> result = highPerfFilter.filter(bigProductList);
        long end = System.currentTimeMillis();

        System.out.println("筛选结果数量:" + result.size());
        System.out.println("耗时:" + (end - start) + "ms");
    }
}
核心优化点
  1. 提前终止matchAllFilters 方法中,只要商品不匹配一个过滤器,立即返回 false,避免无效计算;
  2. 分场景处理:小数据量用普通循环,大数据量用并行流,平衡并行开销;
  3. 减少对象创建:单个商品过滤时,避免频繁创建 List,提升内存利用率;
  4. 线程池复用:使用 ForkJoinPool 适配并行处理,避免重复创建线程。

补充总结

  1. 动态过滤:通过 DTO 接收前端参数,动态组装过滤器,适配业务中 “用户自定义筛选条件” 的场景,符合开闭原则;
  2. 高性能过滤:针对大数据量优化,通过 “提前终止 + 分场景处理 + 并行计算” 降低耗时,适合电商商品列表、日志筛选等数据量大的场景;
  3. 扩展建议:实际项目中可结合 Spring 的@Component将过滤器注册为 Bean,通过配置文件管理过滤规则,进一步降低耦合。

Logo

电商企业物流数字化转型必备!快递鸟 API 接口,72 小时快速完成物流系统集成。全流程实战1V1指导,营造开放的API技术生态圈。

更多推荐