今天,我做的这个系统的业务方提了一个小业务大改的需求。我的内心是一万句MMP的T﹏T。
大概情况是这样子的:
某个业务曾经保存了3个字段:
字段A,字段B,字段C
其中每个字段大概夹杂着大量的if校验并同时影响着主流程。
现在要改成:
字段C,字段D,字段E,字段F
对主流程影响的结果不变,但是校验规则基本上算是翻新重做了。
简单分析以下发现,其实还有一个隐藏需求是,本次改动不会影响到正在运行的业务流程。
鉴于需求方天天以改需求为乐,其实我很自然而然的就想到了设计模式中的策略模式,新增一个versionId字段,并根据流程的versionId走V1的校验或者走V2的校验。(不,其实我是想根据createdTime来判断新老版本的)
回顾一下策略模式我们大概需要:xxxStrategy接口
xxxStrategyV1类
xxxStrategyV2类
以及一个xxxManager或者xxxFactory来获取具体的 策略。
但是最近我在学习Java8的lamdba和之前很少用到的Enum,我突然想到:我是不是可以用枚举来代替工厂类?
策略模式中可替换的具体算法我是不是可以用lamdba的Predicate或Function来做?
于是便有了以下代码:
public enum xxxStrategy{
v1(.....),
v2(....);
private Consumer paramCheck;
private Function getProcessType;
public static xxxStrategy getxxxVersion(BusinessObject o){
.......
}
}
写起来其实很简单,首先将老的入参校验,与流程判断的代码改造成lamdba并往枚举中V1里面丢,
然后再去写V2的入参校验与流程判断。
写完以后,我似乎感觉代码有一点怪怪的。我貌似也说不清楚为什么。。
仔细思考了一下以后,发现了原因。这里我使用了枚举来管理业务逻辑,而项目中其他的业务逻辑全都放在spring的service中进行管理。
通过枚举的静态方法获取策略本质上是静态工厂,脱离了spring的体系以后,似乎与整个项目风格不合。有一种oop中出了一个叛徒的感觉-_-#。
为此我大概反思了一下。我为什么非要看起来那么oop?或者说这一段与整个项目风格迥异的代码该不该写?
使用oop是为了方便的继承,安装接口便于代码复用。当然我这V1,V2Strategy根本不需要代码复用,只需要重复调用即可。写成util应该也完全可以。
业务代码不归spring管,这么写好么?依赖注入是用来解决组件间复杂的循环依赖和复杂的初始化工作的。这块策略与策略工厂似乎完全没有必要去依赖注入。
如果上面2条都成立,我突然发现,貌似绝大部分的service似乎完全没有必要强行写成service,反正都是只用一次的业务代码,做成static貌似没啥毛病的样子啊。
说实话写到这里我其实有点点混乱,不过我还是把这次代码改造记录下来吧,
欢迎有兴趣的大佬讨论一下。