
本文介绍使用泛型方法统一处理继承关系下的搜索过滤器构建逻辑,避免因返回类型不同导致的代码冗余,同时指出继承设计的潜在风险并推荐更健壮的接口+组合方案。
本文介绍使用泛型方法统一处理继承关系下的搜索过滤器构建逻辑,避免因返回类型不同导致的代码冗余,同时指出继承设计的潜在风险并推荐更健壮的接口+组合方案。
在 Java 开发中,当存在多个功能高度一致、仅因参数或返回类型差异(如父子类)而被迫重复编写逻辑时,典型的“复制粘贴式”实现不仅违反 DRY 原则,还显著增加维护成本与出错概率。您提供的 getWarehouseSimpleSearchFilter 和 getWarehouseSearchFilter 两个私有方法,核心逻辑完全相同:根据传入的 carrierIds 和 shipperIds 集合是否为空,决定是否调用权限校验、是否从授权上下文动态加载公司 ID,并最终设置对应字段后返回过滤器对象。
✅ 首选方案:泛型方法 + 上界约束
最直接且安全的重构方式是将其合并为一个泛型方法,利用 WarehouseSimpleSearchFilter 作为基类的继承关系,通过类型参数限定确保类型安全:
private <t extends warehousesimplesearchfilter> T getWarehouseSearchFilter(
Set<long> carrierIds,
Set<long> shipperIds,
Authorization authorization,
T searchFilter) {
if (CollectionUtils.isEmpty(carrierIds) && CollectionUtils.isEmpty(shipperIds)) {
final Set<long> newCarrierIds = getCompanyIds(WarehousePermission.READ_AVAILABLE, authorization);
final Set<long> newShipperIds = getCompanyIds(WarehousePermission.READ_COMPANY, authorization);
searchFilter.setCarrierIds(newCarrierIds);
searchFilter.setShipperIds(newShipperIds);
return searchFilter;
}
if (!CollectionUtils.isEmpty(carrierIds)) {
checkPermission(WarehousePermission.READ_AVAILABLE, authorization);
searchFilter.setCarrierIds(Collections.unmodifiableSet(carrierIds));
}
if (!CollectionUtils.isEmpty(shipperIds)) {
checkPermission(WarehousePermission.READ_COMPANY, authorization);
searchFilter.setShipperIds(Collections.unmodifiableSet(shipperIds));
}
return searchFilter;
}</long></long></long></long></t>
调用时无需任何修改,类型推断自动生效:
WarehouseSimpleSearchFilter simpleFilter = getWarehouseSearchFilter(carrierIds, shipperIds, auth, new WarehouseSimpleSearchFilter()); WarehouseSearchFilter enrichedFilter = getWarehouseSearchFilter(carrierIds, shipperIds, auth, new WarehouseSearchFilter());
⚠️ 关键注意事项
- 返回值语义澄清:当前方法始终返回入参 searchFilter 的引用(即“就地修改”)。若无链式调用需求(如 filter.setX(...).setY(...)),建议将返回类型改为 void,语义更清晰,也避免误导调用方以为发生了对象重建。
- 继承设计存疑:WarehouseSearchFilter extends WarehouseSimpleSearchFilter 表面看是“增强版”,但实际违背了面向对象中“is-a”的本质——一个带 search 字段和 isLocked 状态的完整搜索过滤器,逻辑上并非一个“简单过滤器”。这种为复用字段而滥用继承的做法极易演变为脆弱基类问题:未来对 WarehouseSimpleSearchFilter 的任意修改(如新增校验逻辑、重写 setter)都可能意外破坏子类行为。
? 更优演进方向:接口抽象 + 组合优先
推荐解耦行为契约与具体实现:
- 定义统一能力接口:
public interface WarehouseSearchFilter { void setCarrierIds(Set<long> ids); void setShipperIds(Set<long> ids); // 可选:定义只读访问方法,支持统一处理逻辑 }</long></long> - 让两个类独立实现该接口(取消继承):
public class WarehouseSimpleSearchFilter implements WarehouseSearchFilter { /* 实现 */ } public class WarehouseSearchFilter implements WarehouseSearchFilter { /* 实现 */ } - 泛型方法改用接口约束(更松耦合):
private <t extends warehousesearchfilter> T configureWarehouseFilter( Set<long> carrierIds, Set<long> shipperIds, Authorization auth, T filter) { // 同上逻辑,仅依赖接口方法 }</long></long></t>
此设计提升了可测试性(可 mock 接口)、可扩展性(新增过滤器类型只需实现接口),并彻底规避继承带来的紧耦合风险。代码复用应通过组合、委托或工具类静态方法达成,而非牺牲模型准确性换取短期便利。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











