如何避免使用instanceof?基于接口AAA的服务逻辑优化问询
避免使用instanceof的几种解决方案
给你几个可行的实现方案,适配你的场景(Service里有BBB/CCC通用逻辑,method1、method2依赖同一私有方法):
方案一:在接口中定义统一处理方法,让实现类各自实现
把分支逻辑转移到实体类中,Service直接调用接口方法即可,不用判断类型:
- 修改
AAA接口,新增一个接收Service实例的方法(因为要调用Service的通用私有方法,这里可以把私有方法改成protected,或者直接传递Service实例让实现类调用对应方法):
interface AAA { DDD generateDdd(Service service); }
- 让
BBB和CCC实现这个方法:
public class BBB implements AAA { @Override public DDD generateDdd(Service service) { // 直接调用Service的method2,内部可复用通用私有方法 return service.method2(this); } } public class CCC implements AAA { @Override public DDD generateDdd(Service service) { return service.method3(this); } }
- 改造Service的
method1:
private DDD method1(AAA aaa){ // 无需判断类型,直接调用接口定义的方法 return aaa.generateDdd(this); }
这种方式代码最简洁,符合开闭原则,新增实现类时仅需实现接口方法即可。
方案二:使用策略模式解耦类型判断
通过维护「类型-处理器」的映射关系,把不同类型的处理逻辑单独抽成策略类,避免在Service里硬编码类型判断:
- 定义策略接口:
interface AAAStrategy { DDD handle(AAA aaa, Service service); }
- 分别实现BBB和CCC的策略类:
class BBBStrategy implements AAAStrategy { @Override public DDD handle(AAA aaa, Service service) { return service.method2((BBB) aaa); } } class CCCStrategy implements AAAStrategy { @Override public DDD handle(AAA aaa, Service service) { return service.method3((CCC) aaa); } }
- 在Service中初始化策略映射,并改造
method1:
public class Service { private final Map<Class<? extends AAA>, AAAStrategy> strategyMap; public Service() { strategyMap = new HashMap<>(); strategyMap.put(BBB.class, new BBBStrategy()); strategyMap.put(CCC.class, new CCCStrategy()); } public DDD returnDdd(AAA aaa){ // ...原有通用逻辑 return method1(aaa); } private DDD method1(AAA aaa){ AAAStrategy strategy = strategyMap.get(aaa.getClass()); if(strategy == null) { throw new IllegalArgumentException("不支持的AAA类型: " + aaa.getClass()); } return strategy.handle(aaa, this); } // 原有的method2、method3和通用私有方法 private DDD method2(BBB bbb) { commonMethod(); // BBB专属逻辑 return new DDD(); } private DDD method3(CCC ccc) { commonMethod(); // CCC专属逻辑 return new DDD(); } private void commonMethod() { // 通用逻辑实现 } }
这种方式适合不想修改实体类(比如实体类是第三方依赖)的场景,新增实现类只需添加对应的策略类并注册到Map中,无需修改原有Service的核心逻辑。
方案三:使用访问者模式(适合多操作扩展场景)
如果后续需要对BBB/CCC添加更多不同的操作逻辑,访问者模式可以把操作和实体类解耦:
- 定义访问者接口:
interface AAAVisitor { DDD visitBBB(BBB bbb); DDD visitCCC(CCC ccc); }
- 修改
AAA接口,添加接收访问者的方法:
interface AAA { DDD accept(AAAVisitor visitor); }
- 让
BBB和CCC实现accept方法:
public class BBB implements AAA { @Override public DDD accept(AAAVisitor visitor) { return visitor.visitBBB(this); } } public class CCC implements AAA { @Override public DDD accept(AAAVisitor visitor) { return visitor.visitCCC(this); } }
- 改造Service的
method1:
public class Service { public DDD returnDdd(AAA aaa){ // ...原有通用逻辑 return method1(aaa); } private DDD method1(AAA aaa){ return aaa.accept(new AAAVisitor() { @Override public DDD visitBBB(BBB bbb) { return method2(bbb); } @Override public DDD visitCCC(CCC ccc) { return method3(ccc); } }); } private DDD method2(BBB bbb) { commonMethod(); // BBB专属逻辑 return new DDD(); } private DDD method3(CCC ccc) { commonMethod(); // CCC专属逻辑 return new DDD(); } private void commonMethod() { // 通用逻辑实现 } }
这种方式代码复杂度稍高,但适合需要对实体类扩展多种操作的场景,新增操作只需新增访问者实现即可,不用修改实体类。
内容的提问来源于stack exchange,提问作者Matexon
相关产品推荐
相关产品推荐

