在纯面向对象的代码中,使用switch语句是代码异味(smell)。这并不意味着它们本质上是错误的,只是你需要仔细考虑是否使用。要特别小心。
我的定义中,switch还包括那些可以轻松重写为switch语句的if-then-else语句。
Switch语句可能表明您没有在操作数据的地方定义行为,并且没有充分利用子类型多态性。
当使用面向对象语言时,您不必强制以面向对象的方式编程。因此,如果选择使用更功能性或基于对象的编程风格(例如,使用仅包含数据而不包含行为的DTO,而不是更丰富的领域模型),则使用switch语句没有问题。
最后,在编写面向对象程序时,switch语句非常方便,可以用于在外部非面向对象世界进入您的面向对象模型时将外部实体转换为面向对象概念。最好尽早进行这种转换。例如:从数据库中获取的int可以使用switch语句转换为对象。
int dbValue = ...;
switch (dbValue)
{
case 0: return new DogBehaviour();
case 1: return new CatBehaviour();
...
default: throw new IllegalArgumentException("cannot convert into behaviour:" + dbValue);
}
编辑 阅读了一些回答之后。
Customer.isInvestable
:很好,多态性。但是现在你将这个逻辑与客户联系起来,你需要为每种类型的客户都实现不同的行为而创建一个子类。据我所知,继承不应该被用于这种方式。你希望客户类型是 Customer
的属性,或者有一个函数可以决定客户的类型。
双重分派:两次多态性。但是你的访问者类本质上仍然是一个大开关,它有一些与上面解释的相同的问题。
此外,根据 OP 的示例,多态性应该基于客户的类别,而不是基于 Customer
本身。
切换值很好:好吧,但是切换语句在大多数情况下是用于测试单个 int
,char
,enum
等值,而不是 if-then-else,在那里可以测试范围和更奇特的条件。但是如果我们在此单个值上调度,并且它不在我们的 OO 模型边缘,如上面所述,那么似乎经常使用 switch 来调度类型,而不是值。或者:如果您不能使用 switch 替换 if-then-else 的条件逻辑,那么您可能没有问题,否则您可能有问题。因此,我认为 OOP 中的 switch 是代码异味,而语句
在类型上切换是不好的 OOP 风格,
在值上切换很好。
本身就过于简单化了。
回到起点:一个 switch
不是坏的,它只是不总是非常 OO。您不必使用 OO 来解决问题。如果您确实使用 OOP,则需要特别注意切换。