有哪些方法可以在代码中消除switch
语句的使用?
有哪些方法可以在代码中消除switch
语句的使用?
Switch语句本身并不是反模式,但如果你在编写面向对象的代码时,应该考虑是否可以使用多态来代替使用switch语句。
通过多态,可以这样实现:
foreach (var animal in zoo) {
switch (typeof(animal)) {
case "dog":
echo animal.bark();
break;
case "cat":
echo animal.meow();
break;
}
}
变成了这样:
foreach (var animal in zoo) {
echo animal.speak();
}
typeof
的 switch
语句,而且这个回答也没有建议在其他情况下如何绕开 switch
语句或原因。 - Kevin通常,类似的switch语句散布在程序中。如果你在一个switch中添加或删除一个子句,经常需要查找和修复其他switch语句。
如果您的(伪)代码看起来像:
class RequestHandler {
public void handleRequest(int action) {
switch(action) {
case LOGIN:
doLogin();
break;
case LOGOUT:
doLogout();
break;
case QUERY:
doQuery();
break;
}
}
}
这段代码违反了开闭原则,并且对每个新类型的动作代码都很脆弱。 为了解决这个问题,你可以引入一个“命令”对象:
interface Command {
public void execute();
}
class LoginCommand implements Command {
public void execute() {
// do what doLogin() used to do
}
}
class RequestHandler {
private Map<Integer, Command> commandMap; // injected in, or obtained from a factory
public void handleRequest(int action) {
Command command = commandMap.get(action);
command.execute();
}
}
Map<Integer,Command>
的代码不需要使用switch吗? - ataulm开关是一种模式,无论是使用switch语句、if else链、查找表、面向对象的多态性、模式匹配或其他方式实现。
您是否想消除“switch语句”或“switch模式”?第一个可以被消除,但第二个只有在能够使用另一种模式/算法时才能消除,而大多数情况下这是不可能的或不是更好的方法。
如果您想从代码中消除switch语句,首先要问的问题是在哪些情况下消除switch语句并使用其他技术是有意义的。不幸的是,这个问题的答案是特定于领域的。
请记住,编译器可以对switch语句进行各种优化。因此,例如,如果您想高效地进行消息处理,则使用switch语句就是最好的选择。但另一方面,基于switch语句运行业务规则可能不是最佳选择, 应该重新架构应用程序。
以下是一些替代switch语句的方法:
Switch本身并不是很糟糕,但如果你在方法中有大量“switch”或“if/else”对对象进行操作,则可能表明您的设计有点“过程化”,并且您的对象只是值桶。将逻辑移到您的对象上,在对象上调用一个方法,让它们决定如何响应。
我认为最好的方法是使用一个好的Map。使用字典,您可以将几乎任何输入映射到其他值/对象/函数。
你的代码应该看起来像这样(伪代码):
void InitMap(){
Map[key1] = Object/Action;
Map[key2] = Object/Action;
}
Object/Action DoStuff(Object key){
return Map[key];
}
每个人都喜欢巨大的if else
块,如此易读!但我很好奇你为什么想要删除switch语句。如果你需要一个switch语句,那么你可能就需要一个switch语句。说真的,这取决于代码在做什么。如果所有switch语句都在调用函数(比如),那么可以传递函数指针。但是否更好的解决方案还有待商榷。
语言在这里也是一个重要因素,我认为。
我认为你需要的是策略模式。
这可以通过多种方式来实现,如其他回答中提到的:
switch
语句进行替换是一个不错的选择:
int state;添加新的行为需要复制
String getString() { switch (state) { case 0 : // state 0 的行为 return "zero"; case 1 : // state 1 的行为 return "one"; } throw new IllegalStateException(); }
double getDouble() {
switch (this.state) { case 0 : // state 0 的行为 return 0d; case 1 : // state 1 的行为 return 1d; } throw new IllegalStateException(); }
switch
并添加新的状态意味着在每个switch
语句中添加另一个case
。if-else
块,但在添加新行为和新状态时仍然存在相同的问题。IState state;每次添加新状态时,您必须添加
String getString() { return state.getString(); }
double getDouble() { return state.getDouble(); }
IState
接口的新实现。在使用switch
时,您需要向每个switch
中添加一个case
。IState
接口及其各个实现中添加新方法。这与以前的负担相同,但现在编译器将检查您是否在每个预先存在的状态上实现了新行为。switch
语句时,我会进行重构。if-else
我并不认同switch语句本质上是坏的这个前提。