【Spring 接口多实现】怎么优雅的获取接口的多实现

使用 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 逻辑吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值