
本文介绍两种专业、可维护的方式,让抽象类中的方法既能默认接收 sortdto,又能适配其他 dto 类型:一是通过统一接口抽象参数行为,二是利用 java 方法重载机制,避免 instanceof 反模式。
本文介绍两种专业、可维护的方式,让抽象类中的方法既能默认接收 sortdto,又能适配其他 dto 类型:一是通过统一接口抽象参数行为,二是利用 java 方法重载机制,避免 instanceof 反模式。
在设计可复用的抽象基类时,常面临一个核心权衡:既要提供开箱即用的默认逻辑,又要为子类或下游项目保留足够的扩展自由度。针对 setExitStatus 这类需根据 DTO 状态返回不同业务码(如 "DATOS"/"SINDATOS")的方法,硬编码依赖 SortDto 会严重限制可复用性。以下是两种符合面向对象设计原则的解决方案:
✅ 方案一:接口抽象 —— 推荐首选(高内聚、易测试、可扩展)
定义一个轻量级契约接口,将“是否含数据”的判断逻辑上移到具体 DTO 实现中,从而解耦抽象方法与具体类型:
// 统一语义接口:所有可参与状态判定的 DTO 都应实现
public interface ExitStatusCapable {
boolean hasData(); // 替代模糊的 isDatos(),语义更清晰
}
各 DTO 实现该接口,封装自身判定逻辑:
public class SortDto implements ExitStatusCapable {
private int totalNumberOfPages;
@Override
public boolean hasData() {
return totalNumberOfPages > 0;
}
// getter/setter...
}
public class ReportDto implements ExitStatusCapable {
private List<string> records;
@Override
public boolean hasData() {
return records != null && !records.isEmpty();
}
}</string>
抽象类中仅依赖接口,逻辑简洁且完全开放:
public abstract class BaseProcessor {
/**
* 根据任意实现了 ExitStatusCapable 的 DTO 返回标准状态码
* 子类无需重写即可支持新 DTO 类型
*/
protected String setExitStatus(ExitStatusCapable dto) {
return dto.hasData() ? "DATOS" : "SINDATOS";
}
}
✅ 优势:
- 符合里氏替换原则与依赖倒置原则;
- 新增 DTO 类型只需实现接口,无需修改抽象类;
- 单元测试可轻松 Mock ExitStatusCapable;
- 避免运行时类型检查,性能与安全性兼得。
✅ 方案二:方法重载 —— 适用于逻辑差异较大场景
当不同 DTO 的判定逻辑本质不同(如涉及多字段组合、外部服务调用等),可提供多个重载方法。抽象类声明所有已知变体,子类按需选择使用:
public abstract class BaseProcessor {
// 默认支持 SortDto
protected String setExitStatus(SortDto sortDto) {
return sortDto.getTotalNumberOfPages() > 0 ? "DATOS" : "SINDATOS";
}
// 扩展支持 ReportDto
protected String setExitStatus(ReportDto reportDto) {
return CollectionUtils.isNotEmpty(reportDto.getRecords()) ? "DATOS" : "SINDATOS";
}
// 支持自定义组合 DTO(如 Pair<dtoa dtob>)
protected String setExitStatus(DtoPair pair) {
return pair.getFirst().hasData() || pair.getSecond().hasData()
? "DATOS" : "SINDATOS";
}
}</dtoa>
⚠️ 注意事项:
- 重载方法必须在同一类中声明(不能靠子类单独添加),否则调用方无法享受编译期多态;
- 若重载数量持续增长,建议回归方案一,避免类膨胀;
- 所有重载方法应保持一致的返回语义(如本例均为 "DATOS"/"SINDATOS"),确保 API 一致性。
❌ 应避免的反模式:Object + instanceof
虽然技术上可行,但以下写法严重破坏可维护性:
// ❌ 不推荐:类型检查分散、难以扩展、违反开闭原则
protected String setExitStatus(Object dto) {
if (dto instanceof SortDto) {
return ((SortDto) dto).getTotalNumberOfPages() > 0 ? "DATOS" : "SINDATOS";
} else if (dto instanceof ReportDto) {
// ...重复类型转换与逻辑
}
throw new IllegalArgumentException("Unsupported DTO type");
}
总结:优先采用接口抽象(方案一),它以最小成本换取最大灵活性;仅当跨类型逻辑存在本质差异且数量可控时,辅以重载(方案二)。二者均能确保抽象类既提供稳健默认行为,又为下游项目留出优雅的定制空间。










