项目中工厂模式的简单使用
1.前提背景:
- 项目中的财务开票管理模块原本对接了开票公司A,可以接口自动对接开具增值税普通电子发票,但是增值税纸质专用发票需要财务线下进行开具然后上传到自己的erp系统中。现在需要对接开票公司B,专门用来开具增值税纸质专用发票的开具。发现接口功能大体相似,都是需要开具和查询两个功能,所以可以使用工厂模式,创建对应的实现类调用对应的方法进行开票。
2.简单思路
-
- 创建一个工厂类(OrderTicketFactory),该工厂通过SpringUtils.getBean()方法返回指定的接口(ITicketService)
- 接口(ITicketService)中包含共有的方法,比如申请开票(callCreateApi)和查询开票接口的接口(callQueryApi)
- 开票公司A和开票公司B调用接口的具体实现类实现接口(ITicketService)并重写接口的方法。
- 在需要调用的地方,注入或者新建工厂类,通过参数获取到对应的接口实现类进行使用
3.代码:
-
OrderTicketFactory
-
/** * 发票实现类工厂 */ @Service public class OrderTicketFactory { private static final String SUFFIX = "orderTicket"; /** * 根据传入的业务类型获取对应的服务类 * beanName 定义为 orderTicket + type */ public ITicketService getOrderService(String type) { return SpringUtils.getBean(SUFFIX + getTicketFactoryType(type)); } private String getTicketFactoryType(String requestType) { if (TicketQueryTypeEnum.B.getValue().equals(requestType)) { return "Etc"; } else { return "Invoice"; } } }
-
-
ITicketService
-
/** * @author 服务申请接口 */ public interface ITicketService { /** * 确认开票 * @param ticket * @param mcEleInvoice * @return */ R callCreateApi(McOrderTicket ticket, McEleInvoice mcEleInvoice); /** * 查询发票信息 * * @param mcEleInvoice * @return */ R callQueryApi(McEleInvoice mcEleInvoice); }
-
-
开票公司B具体实现类
-
/** * 开票公司B发票实类 */ @Service("orderTicketEtc") @Slf4j public class EasyTicketCloudServiceImpl implements ITicketService { /** * 开票 纸质专票 * @param ticket * @param mcEleInvoice * @return */ @Override public R callCreateApi(McOrderTicket ticket, McEleInvoice mcEleInvoice) { try { // // 具体的组装请求,略 } catch (HttpException e) { log.error("调用开票接口报错!",e); return R.error("调用开票接口报错!"); } } /** * 查询 销项发票池 * @param mcEleInvoice * @return */ @Override public R callQueryApi(McEleInvoice mcEleInvoice) { try { // 具体的组装请求,略 } catch (HttpException e) { log.error("调用查询接口报错!",e); return R.error("调用查询接口报错!"); } } }
-
-
开票公司A具体实现类
-
/** * 开票公司A发票实类 */ @Service("orderTicketInvoice") @Slf4j public class EasyTicketCloudServiceImpl implements ITicketService { /** * 开票 电子普票 * @param ticket * @param mcEleInvoice * @return */ @Override public R callCreateApi(McOrderTicket ticket, McEleInvoice mcEleInvoice) { try { // // 具体的组装请求,略 } catch (HttpException e) { log.error("调用开票接口报错!",e); return R.error("调用开票接口报错!"); } } /** * 查询 销项发票池 * @param mcEleInvoice * @return */ @Override public R callQueryApi(McEleInvoice mcEleInvoice) { try { // 具体的组装请求,略 } catch (HttpException e) { log.error("调用查询接口报错!",e); return R.error("调用查询接口报错!"); } } }
-
-
具体的使用:
-
// 我这里直接使用@Autowired注入了,其实也可以直接把工厂类的方法变成静态的方法,就可以直接通过类名调用,类似工具类的使用 @Autowired private OrderTicketFactory orderTicketFactory; // 在具体需要使用的方法里面 // type 为请求类型,使用这个type判断是需要开票公司A还是开票公司B String type = "1" ITicketService ticketService = orderTicketFactory.getOrderService(type); R r = ticketService.callQueryApi(invoice); // 得到对应的开票结果,进行解析使用
-
简单来说就是如此,当同一个方法有多种不同的处理的时候,使用工厂模式。比如发短信有对接多个供应商进行发送、或者同一项业务对应不同的国家有不同的处理,都可以使用简单的工厂模式使代码后期更好维护。