我搜索了很多关于重构大switch
语句的文章。
但他们没有做我想做的事。 我要运行的问题是有一个巨大的switch语句,根据两个不同的值调用不同的方法,让我们说type
和code
目前,我会处理这样的情况:
switch (type)
{
case Types.Type1:
handleType1(code);
break;
case Types.Type2:
handleType2(code);
break;
}
void handleTypeN(code)
{
switch (code)
{
...
}
}
也许结合了工厂和命令模式的东西会帮助我?我一定错过了一些明显的东西。
你会如何重构这段代码?
我可能需要更具体地说明我面临的情况。
我正在接收来自服务器的数据包。数据包包含类型和代码以及一些特定信息。
数据到达后,我会检索数据包的type
和code
,然后在找出switch
之后进入type
语句。 type
调用特定方法来对数据包的code
执行切换。
处理代码的方法现在进一步解码数据包并完成该过程。
+----------+ +----------+
| | Packet | |
| Server | -------------> | Client |
| | | |
+----------+ +----------+
|
|
(Switch on the type of the packet and call a specific method)
|
|
(Switch on the code of the packet and call a specific method)
|
|
(Respond to the server or not)
答案 0 :(得分:4)
Abstract Class Command {
executeSomething();
}
Class typeN extends command {
executeSomething() {
//...
}
}
Class typeM extends command {
executeSomething() {
//...
}
}
replace your switch by :
//my old switch
class commandManager {
processCommand() {
for listOf command in a command buffer
{
onCommand(listOfcommand.command)
}
}
onCommandPoped(command type) {
type.executeSomething()
}
}
you can pass parameters to executeSomething, and you can pass another command
the client code :
{
commandN = new CommandN()
commandManager.postCommand( commandN)
}
在阅读了包服务器用例之后,我认为您可以使用策略模式的变体 http://www.oodesign.com/strategy-pattern.html 您选择在数据包到达时调用的策略 你可以用工厂来建造它。
但你不会杀掉你的开关案例
请记住,服务器可以为许多客户端提供服务。如果它可能是您的开关案例比对象实例更快。
答案 1 :(得分:3)
我认为这取决于您尝试做什么样的代码改进。
如果您真的能够进行大的设计更改,那么我建议使用多态:
创建一个抽象的Packet类 为每种数据包类型创建一个类 创建一个工厂方法,接收原始服务器数据包,并创建正确的数据包类对象 每个数据包类类型都有自己需要执行的作业的实现。
如果您没有进行大型设计更改(通常是这种情况):
保持开关,每个开关盒都会调用一个正确命名的功能,该功能将完成所需的功能。
创建一个矩阵,每个单元格[T,C]将保存一个函数的引用,该函数将处理带有类型T和代码C的数据包。
在程序或课程启动时,矩阵应该启动一次(硬编码,无法解决)
这将为您提供比长开关块更好的性能(直接访问代码,无逻辑比较)
答案 2 :(得分:2)
我构建了一个表格,其中的类型指向带有代码的表格,而这些表格又指向实现函数来调用该类型/代码对。
lookup_type_table[type_low .. type_high] = { lookup_code_table_type_1, lookup_code_table_type_2, ...};
lookup_code_table_type_1[type_1_code_low .. type_1_code_high] = { type1_code1_func_pointer, ... };
int processPacket(int type, int code, paket_t data) {
/* apply boundary checks on the lookup tables here! */
return lookup_type_table[type][code](data);
}
这些表可以实现为链接列表,或者与其他一些更高级的容器实现一起实现,以便在需要时使它们更具动态性。
这可能不像其他一些模式那样面向对象,但我来自C-background:)
在表格中添加映射会增加从其他DSL规范生成它们的可能性,从而提升您的DRY统计数据......
答案 3 :(得分:0)
您可以使用字典词典替换您的开关,这些词典指向实际方法或更好的类来处理数据包。第一个字典使用type作为索引,第二个字典使用代码作为索引。
但是你会通过创建字典替换switch语句,所以最后没有太大的区别。
你也应该看一下状态模式,这种东西就是它实际制作的东西。