关于同一接口有多个不同实现的设计方案
前言
最近公司做了一个银行相关的项目,告诉我公司对接了多个银行的支付,每个银行都有对应的接口要去对接,比如:交易申请,交易取消,支付,回单,交易记录查询等等;这次让我写的是工商银行的支付接口对接,于是我看了下代码,因为比较敏感,所以给大家简单写一下怎么实现的。
public static BankService createService(String bankCode) throws Exception{
if (bankCode == null || bankCode.length() == 0){
throw new ClassNotFoundException("BankCode: is null !");
}else if(BankCode.ZHENGZHOU_BANK.getCode().equals(bankCode)){
return ApplicationContextUtils.getBean(ZhengzhouBankServiceImpl.class);
}else if(BankCode.ZHONGYUAN_BANK.getCode().equals(bankCode)){
return ApplicationContextUtils.getBean(ZhongyuanBankServiceImpl.class);
}else if(BankCode.YOUZHENG_BANK.getCode().equals(bankCode)){
return ApplicationContextUtils.getBean(YouzhengBankServiceImpl.class);
}else if(BankCode.NONGSHANG_BANK.getCode().equals(bankCode)){
return ApplicationContextUtils.getBean(NongshangBankServiceImpl.class);
}else if(BankCode.GONGSHANG_BANK.getCode().equals(bankCode)){
return ApplicationContextUtils.getBean(GongshangBankServiceImpl.class);
}else if(BankCode.XINJIANGNCXYS_BANK.getCode().equals(bankCode)) {
NcxysBankServiceImpl bean = ApplicationContextUtils.getBean(NcxysBankServiceImpl.class);
return bean;
}else if(BankCode.JINAHANG_BANK.getCode().equals(bankCode)){
return ApplicationContextUtils.getBean(JianSheBankServiceImpl.class);
}else if(BankCode.XINJIANGNNONGYE_BANK.getCode().equals(bankCode)){
return ApplicationContextUtils.getBean(NongYeBankServiceImpl.class);
}else if(BankCode.ZHONGUO_BANK.getCode().equals(bankCode)){
return ApplicationContextUtils.getBean(ZhongGuoBankServiceImpl.class);
}else if(BankCode.PINGAN_BANK.getCode().equals(bankCode)){
return ApplicationContextUtils.getBean(PingAnBankServiceImpl.class);
}else if(BankCode.HAINANNCXYS_BANK.getCode().equals(bankCode)){
return ApplicationContextUtils.getBean(HaiNanNcxysBankServiceImpl.class);
}else if(BankCode.HAMI_BANK.getCode().equals(bankCode)){
return ApplicationContextUtils.getBean(HaMiBankServiceImpl.class);
}else{
throw new ClassNotFoundException("BankCode: " + bankCode + " 暂未开通接口服务 !");
}
}
看上去是不是有点头皮发麻,于是我想到有些其他的场景也会这样,比如订单的流转,可能每个状态的订单都会有不同的实现,是不是可以优化一下,不让代码出现这么多的if else。
整活
利用抽象类
抽象类,大家都知道,我们可以把接口写在抽象类里,也可以把方法在抽象类里实现,我们可以借助抽象类的特性,在抽象类中定义好方法和接口,如果这个功能所有的实现类都要实现,那么我们就把接口定义成接口,如果只是某些实现类需要实现的方法,我们就把接口给它实现,直接上代码!
比如pay方法,所有的银行都必须要实现的方法,我就给它定义成抽象方法;transaction方法,只是某个实现类需要实现的方法,我就给直接把方法实现,并抛出异常,意识是没有权限访问。
实现抽象类
在实现抽象类之前,我们要定义每个实现类的编码,这个一定是写死的,比方订单状态,1就是待接单2就是待支付,这个是不可能变得;银行编码001就是工商银行也永远不会变的。再次上代码!
我在每个实现类的@Service上都定义了实现类的命名,然后注意,三个实现类我都实现了pay方法,这是必须的,不实现就报错,但是GongShangHandler还实现了transaction方法,那调用这个方法的时候就会进入到具体的实现类里,不会抛出NO POWER的异常。
controller的编写
使用spring的特性,用map来接受这些Service,map的key就是我们@service里的命名,也就是001,002,003。然后我们直接用map去get传过来code编码,直接就可以获取到实现类,就不需要多个if else判断了。
测试结果