0
点赞
收藏
分享

微信扫一扫

使用策略模式 + 泛型实现通用List过滤框架

是波波呀 4小时前 阅读 1

🧩 问题背景

假设我们有多个实体:

  • User(用户):姓名、年龄、城市
  • Product(商品):名称、价格、分类
  • Order(订单):金额、状态、创建时间

如果每个实体都需要实现“年龄 > 25”、“价格 < 100”、“状态 == PAID”等过滤逻辑,代码将大量重复:

// User 过滤
users.stream().filter(u -> u.getAge() > 25)

// Product 过滤
products.stream().filter(p -> p.getPrice() < 100)

如何设计一个通用接口,让 List<User>List<Product> 都能使用同一套过滤机制?

✅ 解决方案:策略模式 + 泛型 + 函数式接口

我们设计一个通用过滤器框架,核心组件如下:

1. 定义过滤条件模型(FilterCondition)

public class FilterCondition {
    private String field;        // 字段名,如 "age", "price"
    private String operator;     // 操作符:EQ, GT, LT, LIKE, IN 等
    private Object value;        // 比较值

    // 构造函数、getter、setter
    public FilterCondition(String field, String operator, Object value) {
        this.field = field;
        this.operator = operator;
        this.value = value;
    }
}

2. 定义通用过滤策略接口(FilterStrategy)

import java.util.function.Predicate;

public interface FilterStrategy<T> {
    Predicate<T> getPredicate(FilterCondition condition);
}

3. 实现具体策略(以 User 为例)

import java.lang.reflect.Field;
import java.math.BigDecimal;

public class UserFilterStrategy implements FilterStrategy<User> {

    @Override
    public Predicate<User> getPredicate(FilterCondition condition) {
        String field = condition.getField();
        String op = condition.getOperator();
        Object value = condition.getValue();

        return user -> {
            try {
                Field declaredField = User.class.getDeclaredField(field);
                declaredField.setAccessible(true);
                Object fieldValue = declaredField.get(user);

                return compare(fieldValue, op, value);
            } catch (Exception e) {
                return false; // 字段不存在或访问失败,不匹配
            }
        };
    }

    private boolean compare(Object fieldValue, String op, Object value) {
        if (fieldValue == null) return false;

        switch (op) {
            case "EQ":
                return fieldValue.equals(value);
            case "GT":
                if (fieldValue instanceof Comparable && value instanceof Comparable) {
                    return ((Comparable) fieldValue).compareTo(value) > 0;
                }
                break;
            case "LT":
                if (fieldValue instanceof Comparable && value instanceof Comparable) {
                    return ((Comparable) fieldValue).compareTo(value) < 0;
                }
                break;
            case "LIKE":
                if (fieldValue instanceof String && value instanceof String) {
                    return ((String) fieldValue).contains((String) value);
                }
                break;
            case "IN":
                if (value instanceof Iterable) {
                    for (Object v : (Iterable<?>) value) {
                        if (v.equals(fieldValue)) return true;
                    }
                    return false;
                }
                break;
        }
        return false;
    }
}

✅ 支持的操作符:EQ(等于)、GT(大于)、LT(小于)、LIKE(包含)、IN(在集合中)

4. 通用过滤服务(FilterService)

import java.util.List;
import java.util.stream.Collectors;

public class FilterService {

    public <T> List<T> filter(List<T> data, FilterCondition condition, FilterStrategy<T> strategy) {
        Predicate<T> predicate = strategy.getPredicate(condition);
        return data.stream()
                   .filter(predicate)
                   .collect(Collectors.toList());
    }
}

✅ 使用示例

// 准备数据
List<User> users = Arrays.asList(
    new User("张三", 23, "北京"),
    new User("李四", 28, "上海"),
    new User("王五", 30, "北京")
);

// 创建过滤服务
FilterService filterService = new FilterService();
UserFilterStrategy strategy = new UserFilterStrategy();

// 条件:年龄 > 25
FilterCondition ageCondition = new FilterCondition("age", "GT", 25);
List<User> result = filterService.filter(users, ageCondition, strategy);

result.forEach(u -> System.out.println(u.getName())); 
// 输出:李四、王五

✅ 扩展:支持 Product、Order 等任意类型

只需为每个类型实现对应的 FilterStrategy

public class ProductFilterStrategy implements FilterStrategy<Product> {
    @Override
    public Predicate<Product> getPredicate(FilterCondition condition) {
        // 实现类似逻辑,支持 price、name 等字段
    }
}

然后统一调用:

List<Product> filteredProducts = filterService.filter(products, priceCondition, new ProductFilterStrategy());

✅ 高级特性(可选增强)

1. 多条件组合过滤

public <T> List<T> filter(List<T> data, List<FilterCondition> conditions, FilterStrategy<T> strategy) {
    Predicate<T> combined = conditions.stream()
        .map(strategy::getPredicate)
        .reduce(Predicate::and) // 默认AND,可改为OR
        .orElse(t -> true);

    return data.stream().filter(combined).collect(Collectors.toList());
}

2. 使用 MapStruct 或反射缓存提升性能

  • 避免每次过滤都使用反射,可缓存 Field 映射。
  • 或使用 MapStruct 将对象转为 Map<String, Object> 后过滤。

3. 与Spring集成:通过Bean名称获取策略

@Autowired
private Map<String, FilterStrategy<?>> strategies;

public <T> List<T> filter(List<T> data, FilterCondition condition) {
    FilterStrategy<T> strategy = (FilterStrategy<T>) strategies.get(condition.getEntityType());
    return filterService.filter(data, condition, strategy);
}

✅ 适用场景

场景

说明

后台管理系统

用户可自定义查询条件(如“金额 > 100 且 状态=PAID”)

规则引擎

动态加载过滤规则,执行匹配

数据清洗

根据配置规则过滤无效数据

API网关

根据请求参数动态过滤响应数据

✅ 优势总结

优势

说明

高扩展性

新增类型只需实现 FilterStrategy

低耦合

过滤逻辑与业务代码分离

配置化

FilterCondition 可来自数据库、JSON配置

复用性强

一套框架支持所有实体类型

易于维护

条件变更无需修改核心代码




举报

相关推荐

0 条评论