我一直认为大型开关语句是糟糕的OOP设计的症状.在过去,我阅读了讨论这个主题的文章,他们提供了基于OOP的基于OOP的方法,通常基于多态来实例化处理案例的正确对象.
我现在处于一种基于来自TCP套接字的数据流的怪异切换语句的情况,其中该协议基本上由换行符组成,后跟数据行,后跟结束标记.该命令可以是100个不同命令之一,因此我想找到一种方法将这个怪物切换语句减少到更易于管理的状态.
我已经做了一些谷歌搜索,以找到我记得的解决方案,但遗憾的是,谷歌如今已成为各种查询无关结果的荒地.
这类问题有什么模式吗?有关可能实施的任何建议?
我有一个想法是使用字典查找,将命令文本与要实例化的对象类型相匹配.这具有仅仅创建新对象并在表中为任何新命令插入新命令/类型的优点.
但是,这也存在类型爆炸的问题.我现在需要100个新类,而且我必须找到一种方法将它们干净地连接到数据模型."一个真正的开关声明"真的是要走的路吗?
我很感激你的想法,意见或评论.
您可以从命令模式中获得一些好处.
对于OOP,如果行为变化足够小,你可能能够将几个类似的命令折叠成一个类,以避免完全的类爆炸(是的,我可以听到OOP大师已经对此进行尖叫).但是,如果系统已经是OOP,并且100多个命令中的每一个都是真正唯一的,那么只需使它们成为唯一的类并利用继承来整合常见的东西.
如果系统不是OOP,那么我就不会为此添加OOP ...您可以轻松地使用命令模式和简单的字典查找和函数指针,甚至可以根据命令名称动态生成函数调用,具体取决于语言.然后,您可以将逻辑关联的函数分组到库中,这些库表示类似命令的集合,以实现可管理的分离.我不知道这种实现是否有一个好的术语......我总是将它视为一种"调度程序"风格,基于MVC处理URL的方法.
我看到有两个 switch语句作为非OO设计的症状,其中switch-on-enum-type可能被替换为提供抽象接口的不同实现的多种类型; 例如,以下......
switch (eFoo) { case Foo.This: eatThis(); break; case Foo.That: eatThat(); break; } switch (eFoo) { case Foo.This: drinkThis(); break; case Foo.That: drinkThat(); break; }
......也许应该改写成......
IAbstract { void eat(); void drink(); } class This : IAbstract { void eat() { ... } void drink() { ... } } class That : IAbstract { void eat() { ... } void drink() { ... } }
但是,一个 switch语句并不是一个如此强烈的指示,即switch语句应该用其他东西替换.
该命令可以是100个不同命令之一
如果你需要做100件不同的事情中的一件,你就无法避免拥有100路分支.您可以在控制流(switch,if-elseif ^ 100)或数据(从字符串到命令/工厂/策略的100元素映射)中对其进行编码.但它会在那里.
您可以尝试将100路分支的结果与不需要知道该结果的事物隔离开来.也许只有100种不同的方法很好; 如果这会使代码变得难以处理,则无需创建您不需要的对象.