工厂模式的实际运用
工厂模式
开发中,有时会需要根据不同的类型,创建同一接口的对应的不同实现类,再去执行方法。
工厂模式的理解,详情见: https://www.cnblogs.com/expiator/p/8245143.html
示例
以下会举一个例子,不同的反馈类型 type,创建不同的审批处理器对象,进行审批。
自定义注解
/**
* 审批的注解
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Audit {
/**
* 类型
*
*/
String[] types();
/**
* 名称
*
*/
String name() default "";
}
基础接口
不同的类型type,会有不同的处理器去处理。
各个审批处理器的对象,需要实现 AuditHandler 接口。
/**
* 审批处理器接口
*/
public interface AuditHandler {
/**
* 审批
* @param id
* @param type
* @return
*/
void audit(Long id, String type);
}
实现接口的类1
/**
* 审批处理器。
* 通过注解指定处理哪些类型的提议
*
*/
@Audit( types = {"1"}, name = "审批处理器-类型1")
@Component
@Slf4j
public class FirstAuditHandler implements AuditHandler {
@Override
public void audit(Long id , String type) {
log.info("FirstAuditHandler audit.id:{}, type:{}", id, type);
}
}
实现接口的类2
/**
* 审批处理器。
* 通过注解指定处理哪些类型的提议
*
*/
@Audit( types = {"2"}, name = "审批处理器-类型2")
@Component
@Slf4j
public class SecondAuditHandler implements AuditHandler {
@Override
public void audit(Long id, String type) {
//忽略其他审批逻辑
log.info("SecondAuditHandler audit.id:{}, type:{}", id, type);
}
}
实现接口的类3
/**
* 审批处理器。
* 通过注解指定处理哪些类型的提议
*
*/
@Audit( types = {"3","4","5"}, name = "审批处理器-公共")
@Component
@Slf4j
public class CommonAuditHandler implements AuditHandler {
@Override
public void audit(Long id, String type) {
//忽略其他审批逻辑
log.info("CommonAuditHandler audit.id:{}, type:{}", id, type);
}
}
通过类型,获取对象
如果直接对比类型去获取对应的对象,在类型比较多的时候,会有大量的if else
通过map获取,可以减少if else判断。
/**
* 审批的初始化 map,以及获取实例
*/
public class AuditContext {
/**
* 自动审批处理器
*/
private static final Map<String, AuditHandler> AUTO_AUDIT_HANDLERS_MAP = new HashMap<>();
private AuditContext() {
}
/**
* 初始化 map
*
* @param types
* @param name
* @param auditHandler
*/
public static void initMap(String[] types, String name, AuditHandler auditHandler) {
for (String type : types) {
AUTO_AUDIT_HANDLERS_MAP.put(type, auditHandler);
}
}
/**
* 通过类型,获取实例。
* 如果直接对比类型,在类型比较多的时候,会有大量的if else
* 通过map获取,可以减少if else判断。
*
* @param type
* @return
*/
public static AuditHandler getInstance(String type) {
if (StringUtils.isBlank(type)) {
return null;
}
return AUTO_AUDIT_HANDLERS_MAP.get(type);
}
}
类型对应对象的Map初始化
/**
* 初始化审批的处理器及实例的Map
*
*/
@Component
@Slf4j
public class AuditInitService implements ApplicationContextAware, InitializingBean {
private ApplicationContext context;
@Override
public void afterPropertiesSet() {
init();
}
/**
* 设置上下文
* @param applicationContext
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
this.context = applicationContext;
}
/**
* 初始化审批的处理器及实例Map
*/
private void init() {
Map<String, Object> beans = context.getBeansWithAnnotation(Audit.class);
Type[] genericInterfaces;
Class<?> clazz;
Type rawType;
AuditHandler auditHandler;
Audit audit;
String[] types;
String name;
for (Object bean : beans.values()) {
//getGenericInterfaces(): 主要是 获取由此对象表示的类或接口直接实现的接口的Type。
genericInterfaces = bean.getClass().getGenericInterfaces();
for (Type genericInterface : genericInterfaces) {
if (Class.class.isAssignableFrom(genericInterface.getClass())) {
clazz = (Class<?>) genericInterface;
// isAssignableFrom() 用于检测一个类是否继承(或实现)于一个类/接口
if (AuditHandler.class.isAssignableFrom(clazz)) {
auditHandler = (AuditHandler) bean;
//获取AuditHandler实现类上面的@Audit注解
audit = auditHandler.getClass().getAnnotation(Audit.class);
types = audit.types();
name = audit.name();
//初始化审批的处理器及实例Map
AuditContext.initMap(types, name, auditHandler);
log.info(" Init auditHandler[{}] success! The types is {}...", name, Arrays.toString(types));
}
}
}
}
}
}
根据类型创建对象
初始化map的作用体现出来了,不用做太多的if else判断去获取对象类型。
/**
* 反馈提议
*/
@Service
public class SuggestionService {
/**
* 反馈提议后,进行审批
*/
public void suggest(Long id ,String type) {
//忽略其他的反馈逻辑
//...
//获取类型对应的审批处理器对象
//初始化map的作用体现出来了,不用做太多的if else判断去获取对象类型
AuditHandler auditHandler = AuditContext.getInstance(type);
if (auditHandler != null) {
//审批
auditHandler.audit(id, type);
}
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
2019-08-28 在error日志打印异常
2019-08-28 后端开发常用的工具/软件
2018-08-28 表单无法跳转