一个收到消息,分发给不同的处理方法的代码
消息类型已经有十几种了
使用 switch 来根据消息类型跳转不同的处理方法
这个 switch 看起来就很庞大了
请教一下,有没有很好的方式来重构这种情况的代码呢
谢谢~
1
7911364440 2023-01-30 09:35:11 +08:00
策略模式啊
|
2
dddd1919 2023-01-30 09:36:30 +08:00
典型的工厂模式
|
3
yaodao 2023-01-30 09:38:45 +08:00 via iPhone
如果 switch 中的内容比较简单,可以使用枚举类实现抽象方法的简单策略模式。如果比较复杂可以使用监听者模式,广播消息,但每个监听者只处理自己相应的消息。
|
4
TWorldIsNButThis 2023-01-30 09:39:22 +08:00 via iPhone
使用语言内建的 dispatch 功能
也就是子类型多态 |
5
ql562482472 2023-01-30 09:42:17 +08:00
switch 都写不优雅 你到底写成啥样了 发出来看看吧
|
6
ashong 2023-01-30 09:55:21 +08:00 via iPhone 2
handlers[event].action()
|
7
xiangagou 2023-01-30 09:55:42 +08:00 1
最通用的就是工厂+策略模式修改,几乎不用动脑子,其他模式得看业务匹配情况
|
9
nothingistrue 2023-01-30 09:59:48 +08:00 8
十几种还不算多,如果能做成枚举的话,switch 枚举并无不妥。如果太多做不成枚举,或者稍微有那么一两个变异的分支,用 if else 也不丢人。你要知道,你后面的处理是分发不同方法,那么就算有 50 个,代码行也就 150 行,不多。
这里的重点,还是你的消息类型的命名规则。消息类型如果是依次罗列命名,超过 10 个就麻烦,超过 20 个就没法用了。基本上,超过 20 个类型,就该考虑对消息类型的名称进行归纳分级。如果消息类型有良好的命名规则,消息分发可能就不需要 swtich 、if else 了,十几行代码就能搞定。 |
10
cosmain 2023-01-30 10:02:24 +08:00
@nothingistrue 一看就是老 coder 了
|
11
fredli 2023-01-30 10:03:13 +08:00
抽象类继承,消息子类,多态
|
12
zhady009 2023-01-30 10:04:25 +08:00
每个消息类型对应一个 ActionChain, Action 对应具体的业务
关于消息类型和 ActionChain 的关系建立可以是硬编码, 也可以用 Spring 的 BeanPostProcessor+注解的方式 |
13
lysS 2023-01-30 10:14:07 +08:00
信息类型是确定的,可以用数组
|
14
lyusantu 2023-01-30 10:32:12 +08:00
保持 switch 写法
写完后折叠 switch 看起来就比较优雅了 |
15
ianEros 2023-01-30 10:34:07 +08:00
复杂一点写策略,简单逻辑表驱动
|
16
NoKey OP @ql562482472 就是 switch 下面十几个 case ,可能还会增长,到一定时候,肯定不好看,一大片的 case😂
|
17
lambdAlan 2023-01-30 10:38:55 +08:00
策略模式加工厂模式即可
|
18
ianEros 2023-01-30 10:40:23 +08:00
Map<?, Function<?> action> actionsMap = new HashMap<>();
// 初试配置对应动作 actionsMap.put(value1, (someParams) -> { doAction1(someParams)}); actionsMap.put(value2, (someParams) -> { doAction2(someParams)}); actionsMap.put(value3, (someParams) -> { doAction3(someParams)}); // 省略 null 判断 actionsMap.get(param).apply(someParams); |
20
libook 2023-01-30 10:48:16 +08:00
除非消息类型划分不合理,或者重复处理逻辑太多,否则不认为 switch 分枝多有什么问题。
|
21
PiersSoCool 2023-01-30 10:52:24 +08:00
别改了
|
22
cubecube 2023-01-30 10:53:09 +08:00
大规模用策略模式的时候,代码给别人看的时候容易一坨屎,尤其是还是那种 switch 不稳定,状态可能相互有关联的时候。。。
我个人倾向于不改 switch ,处理逻辑复杂的话,内容包在一个函数里面得了 |
23
playtomandjerry 2023-01-30 10:53:34 +08:00 4
不要整花里胡哨的优化,妈的,自己过段时间都看起来费劲,后面人接手能头疼死。switch 内不要放逻辑,直接抽方法出去,已经是很清晰的写法了,简单明了
|
24
shaozelin030405 2023-01-30 10:58:08 +08:00
switch 改成查表法(改成个 map ,根据 key 来看对应哪个情况),然后各个情况可以分成各个方法,好搞
|
25
Ciallo 2023-01-30 10:58:13 +08:00 1
|
26
jorneyr 2023-01-30 10:58:23 +08:00
可以参考 MyBatis 的 TypeHandlerRegistry 把各种消息的处理器集中注册。
|
28
cwcc 2023-01-30 11:07:51 +08:00
我倒是觉得 switch 没啥不妥,但 switch 从代码缩进层面会缩进两次,使用 if else 也才一次。
如果过多的话,建议建个表,然后循环找表对应的方法。或者直接写个表驱动。 不想想太多的话,你只需要做到,让每个 case 的意义十分明确,case 里面的代码不要写逻辑,只调用一两条外面的方法就行了。 |
29
dcncy 2023-01-30 11:14:35 +08:00 via iPhone
各自的方法名与其消息类型保持一致,或者加个前后缀。反射调用方法,两三行代码搞定。
|
30
bxb100 2023-01-30 11:17:10 +08:00
* switch 放到工厂类里面, case 的逻辑都抽成类, 注意 SRP
* 使用责任链, 好处是不需要大量的 switch/if, 坏处是不好理解 |
31
finab 2023-01-30 11:21:14 +08:00
6 楼的表驱动模式
|
32
hyqCrystal 2023-01-30 11:21:27 +08:00
工厂加策略
|
33
qua 2023-01-30 11:23:37 +08:00 via Android 2
如果用工厂,创建策略的时候还不是要判断类型一长串 switch ,有区别吗
|
34
coala 2023-01-30 11:25:42 +08:00
才十几个, 就这样吧, 几十个了可以用策略模式
|
35
potatowish 2023-01-30 11:37:14 +08:00 via iPhone 2
可以使用策略模式,把不同的消息类型处理逻辑划分到独立的实现类中,这些实现类都实现一个公共接口,每个实现类添加一个枚举类型属性,区分消息类型。最后定义一个策略处理类,获取公共接口下所有实现类的对象,按照每次接收的消息类型过滤得到对应的实现类对象,调用其消息处理方法即可。
|
36
Achieve7 2023-01-30 12:20:36 +08:00
这是典型的策略+工厂的场景, 用个 dispatcher 进行分发就好了. 如果能够确定逻辑, 甚至直接拿枚举写也行
|
37
fkdog 2023-01-30 12:27:51 +08:00
分情况。
如果 switch 分支内的逻辑很简单,那么 switch 就是最优解,你做成多态并不会优雅到哪里去,分支判断的逻辑塞到各个子类里去的话反而不直观也不好维护。 如果 switch 分支内的逻辑很复杂,涉及到 CRUD 、缓存、RPC 等调用,那么楼上有答案。 |
38
levelworm 2023-01-30 12:36:55 +08:00 via Android
我感觉 switch 里每项不多的话,还是它最优雅。
|
39
jinsongzhao 2023-01-30 12:51:28 +08:00
把一个 switch 分门别类,变成多个 switch 或 if else ,可读性就挺好了。
实在想减少代码,只能创建一个类型值和函数名称的对应表,然后把 switch 替换为通过类型查表得到函数名,然后反射调用。这样语句是少了,类型和函数名也都放在一起,类型和函数对应关系可读性优化了,但是逻辑复杂了,总体可读性其实是下降了。 |
40
3dwelcome 2023-01-30 12:52:56 +08:00
我以前写过一篇 switch 的文章,"只有放弃英文代码,写全中文代码,才能支撑起千变万化的需求。", 可惜大家回复太热情,直接进水区了。
单文件太大可以分几个子文件,但 Op 最主要的问题,就是消息的命名方式。 起不好英文函数名字,后续维护就是灾难。 |
41
WilliamYang 2023-01-30 12:58:05 +08:00
switch 分发已经是最优解了
|
42
pennai 2023-01-30 12:58:42 +08:00
策略模式先苟着,当策略模式也感觉过多的时候可以用规则引擎
|
43
s1e42NxZVE484pwH 2023-01-30 15:07:28 +08:00
|
44
ZiLong 2023-01-30 16:10:36 +08:00
我看过一篇文章,switch 最大的问题还是扩展性问题(违背了开闭原则),然后里面列举了 7 种方式改善 switch ,基本的思想和方法都覆盖到了 [重构 Java switch 语句的七种方法]( https://juejin.cn/post/7149189951895617550)
|
45
Cloutain 2023-01-30 17:32:07 +08:00
那完了,反汇编引擎就是 switch 一层套一层
|
47
mmuggle 2023-01-30 17:41:50 +08:00
既然要重构,那就用点设计模式吧,策略模式加工厂模式
|
48
fuis 2023-01-30 18:25:41 +08:00
别改了,能用就行
|
49
zhouhu 2023-01-30 19:40:35 +08:00
升级到 Java 17
|
50
newmlp 2023-01-31 09:37:40 +08:00
十几种还多啊,一点都不多,没必要重构
|
51
vinceall 2023-01-31 16:13:08 +08:00
我喜欢用枚举+函数接口,映射到不同处理策略
|