在写业务代码的时候我有时想写一些策略模式工厂模式类似的代码拆分业务,可是在spring下有一些局限性.我们已经使用了spring来管理对象的初始化,我们就没法写一些类似于
map.put("key",new object())
的代码.其次同一接口下多个实现类需要使用
@Qualifier("a")
@Qualifier("b")
来区分,那么最终我们的代码大概会写成这个样子
public class WxEventHandleFactory {
@Autowired
@Qualifier("scan")
private WxEventHandle scanHandle;
@Autowired
@Qualifier("subscribe")
private WxEventHandle subscribeHandle;
@Autowired
@Qualifier("unsubscribe")
private WxEventHandle unsubscribeHandle;
public WxEventHandle getHandle(String event) {
if (WxEventType.SUBSCRIBE.getCode().equals(event)) {
return subscribeHandle;
} else if (WxEventType.UNSUBSCRIBE.getCode().equals(event)) {
return unsubscribeHandle;
} else if (WxEventType.SCAN.getCode().equals(event)) {
return scanHandle;
}
return null;
}
}
这段代码就是根据微信公众号不同的消息,拆分了不同处理代码.不好的点就是我们的策略方法会不断的膨胀的,但这也不是不能接受,我在flink的某个连接redis做状态存储的开源项目下也看到过更大的类似方法,不过是用switch 拆分罢了.
那么我们有没有更好的办法呢?
我们可不可以通过一些类似标记的方式给我们业务类打上独有的标记?
注解是一个不错的方案
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface CallBack {
TypeEnum[] value();
}
这里value为什么是一个数组呢,因为我希望多个策略使用同一个类处理.
我们怎么从spring的管理中获取这些被我们标记的类呢?
bean实例化后会注入ApplicationContext
@Component
public class MyBean {
@Autowired
private ApplicationContext context;
}
接下来我们只需要将标有@CallBack的类统一使用数据结构保存起来,每次根据不同TypeEnum获取即可,其次为了方便调用,我们所有的业务类肯定需要实现相同的方法
public interface BaseStrategyCallBack {
void doMethod(MyContext myContext);
}
@PostConstruct(bean初始化前执行,相当于init)
@Component
public class FactoryStrategy {
private static Map<TypeEnum, BaseStrategyCallBack> map = new ConcurrentHashMap<>();
@Autowired
private ApplicationContext context;
public static BaseStrategyCallBack createDoMethod(TypeEnum typeEnum) {
return map.get(doTypeEnum);
}
@PostConstruct
public void init() {
Map<String, Object> beansMap = context.getBeansWithAnnotation(CallBack.class);
beansMap.values()
.forEach(i -> {
OrderCallBack doTypeAnnotation = i.getClass().getAnnotation(CallBack.class);
for(ItemTypeEnum e : doTypeAnnotation.value()){
map.put(e, (BaseStrategyCallBack) i);
}
});
}
}
编写业务类
@Log4j2
@Service
@CallBack(TypeEnum.test)
public class StrategyTest implements BaseStrategyCallBack {
@Override
public void doMethod(MyContext myContext) {
//业务逻辑
}
}
调用
FactoryStrategy.createDoMethod(typeEnum).doMethod(myContext);
至此我们就实现了基于spring的代码拆分,根据不同的枚举获取不同的业务类.
ps:我平时是不看spring相关书籍去学习的,当工作中需要的时候可能会点进去看一丢丢源码也是属于看过就忘.但是有一点就是一定要去看官方文档,毕竟spring的文档算是开源项目里最完善的一批了.理解了ioc,aop.你就有了思考的脉络,剩下东西,我愿意称为机制而不是技术,所以机制的东西,在不会的时候去看文档查一查就好.况且现在还有chatgpt,查文档更是一绝.其次我也很少看设计模式相关的东西,因为只要你心中有类,接口,抽象类的概念,那你就可以梳理代码的结构,以不变应万变我觉得才是更好的方式.当然这是我个人极端的想法,设计模式还是需要看的,只是我目前还没有多余的时间,之前一直都是写一些底层原理的文章,是因为我个人比较痴迷这些东西.最近尝试写一些比较业务的东西,展示一下工作中的一些思路.
网友评论