使用 Spring 优雅获取接口的多现实
java 一个最显著的特征是面向接口编程。如果业务中一个接口有多个实现,我们怎么处理?
1、设计模式之 工厂模式?策略模式?
2、Spring 注入给不同的实现使用不同的命名?
3、。。。
以上的方式是不是都免不了写 if else,那有没有优雅一点的方式呢,下面就举例介绍:
ISyncInfoService , 同步信息的接口:
public interface ISyncInfoService {
/**
* 执行信息同步
*/
void execute(SyncObj syncObj);
/**
* 用以区分不同实现不同的 type,以便 Factory 可以获取到正确的 ISyncInfoService 实现
*/
SyncTypeEnum getType();
}
同步信息有多个实现,需要根据不同的场景给不同的第三方同步数据,需要实现 ISyncInfoService 接口
PartnerA
public class SyncInfo2PartnerAService implements ISyncInfoService {
public void execute(SyncObj syncObj) {
//TODO sync Info to Partner A
// 可能要有不同的业务逻辑, 假设 Partner A 提供的是 RPC 接口
}
public SyncTypeEnum getType() {
return SyncTypeEnum.TYPE_A;
}
}
PartnerB
public class SyncInfo2PartnerBService implements ISyncInfoService {
public void execute(SyncObj syncObj) {
//TODO sync Info to Partner B
// 可能要有不同的业务逻辑,假设 Partner B 提供的是 http 服务
}
public SyncTypeEnum getType() {
return SyncTypeEnum.TYPE_B;
}
}
public enum SyncTypeEnum {
// 演示类型,根据自己业务定义
TYPE_A(1, "sync to a"),
TYPE_B(2, "sync to b"),
;
private int code;
private String desc;
SyncTypeEnum(int code, String desc) {
this.code = code;
this.desc = desc;
}
public int getCode() {
return this.code;
}
public int getTypeBySource(int source) {
SyncTypeEnum[] var1 = values();
int var2 = var1.length;
for(int var3 = 0; var3 < var2; ++var3) {
SyncTypeEnum enu = var1[var3];
if (enu.getCode() == id) {
return enu;
}
}
return null;
}
}
@Component
public class SyncInfoServiceFactory implements ApplicationContextAware {
private static Map<SyncTypeEnum, ISyncInfoService> serviceMap;
public static <T extends ISyncInfoService> T getService(SyncTypeEnum source) {
return (T) serviceMap.get(source);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
// 服务启动自动获取 ISyncInfoService 对应的实现,放入到 serviceMap 中,后期使用直接从 serviceMap 中 get
Map<String, ISyncInfoService> beansOfType = applicationContext.getBeansOfType(ISyncInfoService.class);
serviceMap = new HashMap<>();
beansOfType.forEach((key, value) -> serviceMap.put(value.getType(), value));
}
}
调用者 BusinessCenterService
调用 ISyncInfoService#execute() 根据不同的场景使用 A 或 B,不使用 if else
@Component
public class BusinessCenterService {
public void syncInfo2Partner(BuinsessObj bo) {
// 通过 SyncInfoServiceFactory ,根据不同的入参 source 值从 serviceMap 中获取对应 实现
ISyncInfoService syncInfoService = SyncInfoServiceFactory.getService(SyncTypeEnum.getTypeBySource(bo.getSource()));
if (orderSyncService != null) {
SyncObj so = null;
// TODO 构造要同步的 so 信息
syncInfoService.execute(so);
}
}
}
public class BuinessObj {
private int source;
//TODO ...
public int getSource () {
return this.source;
}
}
以上就是在 Spring 中注入方式的一个接口,多个实现时,完成不同的业务的实现,利用 ApplicationContext#getBeansOfType 获取实现的方式,可以使用在对外提供统一接口,内部路由的方式;也可使用在不同的业务的不同阶段;或者是需要调用不同的第三方接口或服务完成业务信息同步等。快来试试改造你的 if else 逻辑吧。