🧩 问题背景
假设我们有多个实体:
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网关 | 根据请求参数动态过滤响应数据 |
✅ 优势总结
优势 | 说明 |
高扩展性 | 新增类型只需实现 |
低耦合 | 过滤逻辑与业务代码分离 |
配置化 |
|
复用性强 | 一套框架支持所有实体类型 |
易于维护 | 条件变更无需修改核心代码 |