工厂模式简介
在工厂模式中,不会对外暴露创建对象的具体逻辑,而且是通过使用一个共同的接口指向创建的对象。工厂模式是一种创建型设计模式,主要意图是定义一个创建对象的接口,让其子类决定实例化哪个工厂类,工厂模式使其创建过程延迟到子类中进行。简单的说就是为了提供代码的扩展性,屏蔽每个功能类中具体的实现逻辑,外部只是调用,可以去掉众多的if-else。
策略模式简介
策略模式是一种行为型设计模式,同样也可以去掉众多的if-else。使用场景:
1、如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地
让一个对象在许多行为中选择一种行为。
2、一个系统需要动态地在几种算法中选择一种。
3、如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。
业务场景
通过OCR识别不同的票据,解析票据的详细信息,例如:火车票、机票、出租车票、增值税电子普通发票等。
代码实现
- 创建一个接口,用来识别票据
public interface ITicketIdentifyService {
/**
* 通过OCR识别票面信息
* @param type 票据类型
* @param file
* @return
*/
OcrTicketVo identifyTicket(String type, MultipartFile file);
}
- 创建接口的具体实现类
//火车票
@Service
@Slf4j
public class TrainIdentifyService implements ITicketIdentifyService {
@PostConstruct
private void init(){
log.info("===============================注册火车票开始");
OcrIdentifyFactory.register(TicketTypeEnum.TRAIN.getCode(),this);
log.info("===============================注册火车票结束");
}
@Override
public TicketVo identifyTicket(String type, MultipartFile file) {
//识别火车票并返回结构化信息
}
}
//机票
@Service
public class PlaneIdentifyService implements ITicketIdentifyService {
@PostConstruct
private void init(){
log.info("===============================注册机票开始");
OcrIdentifyFactory.register(TicketTypeEnum.AIRPLANE.getCode(),this);
log.info("===============================注册机票结束");
}
@Override
public OcrTicketVo identifyTicket(String type, MultipartFile file) {
//识别机票并返回结构化信息
}
}
- 创建工厂类
/**
* OCR识别工厂类,策略模式与工厂模式搭配将策略类注册到工厂中
*/
public class OcrIdentifyFactory {
private static Map<String, ITicketIdentifyService> ocrFactory = new HashMap<>();
/**
* 通过策略工厂注入IOcrIdentifyService接口的各个实现类
* @param type 票据类型
* @param ocrIdentifyService 实现类
*/
public static void register(String type, ITicketIdentifyService ocrIdentifyService){
if(StringUtil.isNotEmpty(type)){
ocrFactory.put(type,ocrIdentifyService);
}
}
/**
* 根据票据类型获取不同的实现类
* @param type 票据类型
* @return
*/
public static ITicketIdentifyService createObj(String type){
return ocrFactory.get(type);
}
}
- 动态调用实现类识别不同的票据
//type:票据类型编码
//file:票据文件
OcrTrainTicketVo trainTicketVo = (OcrTrainTicketVo) OcrIdentifyFactory.createObj(TickeTypeEnum.TRAIN.getCode()).identifyTicket(type, file);