项目学习——简单工厂模式优化
一、前言
最近接触了一个项目,在这个项目中有一个EventHandler的概念,用于解决KAFKA不同类型的数据。
为了架构设计,开发成员在这里使用了工厂模式来处理这块请求。但是他通过引入spring的InitializingBean接口,解决了简单工厂中可能会出现大量的if-else的问题。
二、简单工厂模式设计图
在这个项目中有一个EventHandler基本的工厂模式架构图是这样的。
本项目的EventHandler架构大致也是这样的。
三、传统的简单工厂缺点
通过上图的可以发现,通过简单工厂我们暴露给调用方的只有HandlerFactor和AbstarctHandler,这样就可以将大量的实现隐藏起来。
问题是:工厂本身是如何选择对应的handler实现呢?
解决的方案为:在getHandler中写if-else对condition进行判断,进而创建。
// 伪代码
class HandlerFactor{
public AbstractHandler getHandler(Condition...){
if(condition1 is true){
return FuncAHandler;
}else if(condition2 is true){
return FuncBHandler;
}else if(condition3 is true){
return FuncCHandler;
}else{
throw Error; // .....
}
}
}
经验丰厚的小伙伴一看就知道if-else当处理大量的实现的时候就会形成坏味道。一种解决方案是通过hashMap存放创建好的对象在getHander时使用map.get(condition),另一种方式是用责任链模式解决。但是无论哪一种模式都会出现如下所描述的代码片段。
class demo{
# hashmap
{
map.put(condition1, FuncAHandler);
map.put(condition1, FuncBHandler);
map.put(condition1, FuncCHandler);
....
}
# 责任链
{
FuncAHandler.netx = FuncBHandler;
FuncBHandler.netx = FuncCHandler;
FuncCHandler.netx = null;
...
}
}
这样其实并没有很好的解决代码问题,还是存在冗余。
四、解决方案
目的如何解决hashmap重复放入的问题。我们可以考虑一下,我们是否可以设置一种一旦Handler创建完成之后,该对象就自动被放入HashMap中的方法。
答案是肯定的,spring提供了InitializingBean接口。里面存在afterPropertiesSet()方法就可做到这一点。
public interface InitializingBean {
void afterPropertiesSet() throws Exception;
}
在AMS的项目中实现是这样的
@Override
public void afterPropertiesSet() throws Exception {
if (getEventEnum() != null && getEventHandlerFactory() != null) {
// 调用put过程 bean放入 this就是当前handler对象
getEventHandlerFactory().registHandler(getEventEnum(), this);
}
}
// 放入bean
@Override
public void registHandler(EventEnum eventEnum, EventHandler handler) {
if (eventEnum != null && handler != null && getHandlerMap() != null) {
getHandlerMap().put(eventEnum.getCode(), handler);
} else {
//打印日志,提示注册失败
throw new BizException(CommonErrorCodeEnum.SERVICE_NOT_REGIST, "注册事件类型对应的执行器对象失败");
}
}