有什么方法可以消除代码中交换机的使用?
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(); }
请参阅切换语句气味:
通常,类似的switch语句分散在整个程序中.如果在一个开关中添加或删除子句,则通常还必须查找并修复其他子句.
这两种重构和重构到模式必须解决这个办法.
如果您的(伪)代码如下所示:
class RequestHandler { public void handleRequest(int action) { switch(action) { case LOGIN: doLogin(); break; case LOGOUT: doLogout(); break; case QUERY: doQuery(); break; } } }
此代码违反了开放封闭原则,并且对于出现的每种新类型的操作代码都很脆弱.要解决这个问题,你可以引入一个'Command'对象:
interface Command { public void execute(); } class LoginCommand implements Command { public void execute() { // do what doLogin() used to do } } class RequestHandler { private MapcommandMap; // injected in, or obtained from a factory public void handleRequest(int action) { Command command = commandMap.get(action); command.execute(); } }
如果您的(伪)代码如下所示:
class House { private int state; public void enter() { switch (state) { case INSIDE: throw new Exception("Cannot enter. Already inside"); case OUTSIDE: state = INSIDE; ... break; } } public void exit() { switch (state) { case INSIDE: state = OUTSIDE; ... break; case OUTSIDE: throw new Exception("Cannot leave. Already outside"); } }
然后你可以引入一个'State'对象.
// Throw exceptions unless the behavior is overriden by subclasses abstract class HouseState { public HouseState enter() { throw new Exception("Cannot enter"); } public HouseState leave() { throw new Exception("Cannot leave"); } } class Inside extends HouseState { public HouseState leave() { return new Outside(); } } class Outside extends HouseState { public HouseState enter() { return new Inside(); } } class House { private HouseState state; public void enter() { this.state = this.state.enter(); } public void leave() { this.state = this.state.leave(); } }
希望这可以帮助.
switch是一种模式,无论是用switch语句实现的,if else链,查找表,oop多态,模式匹配还是其他.
您想要消除" switch statement "或" switch pattern "的使用吗?第一个可以被消除,第二个可以被消除,只有在可以使用另一个模式/算法时,并且大部分时间是不可能的,或者这不是更好的方法.
如果你想从代码中消除switch语句,首先要问的问题是消除switch语句和使用其他技术是有意义的.不幸的是,这个问题的答案是特定领域的.
请记住,编译器可以进行各种优化来切换语句.因此,例如,如果您想要有效地进行消息处理,那么切换语句几乎是可行的方法.但另一方面,基于switch语句运行业务规则可能不是最好的方法,应该重新构建应用程序.
以下是switch语句的一些替代方法:
查找表
多态性
模式匹配(特别用于函数式编程,C++模板)
切换本身并没有那么糟糕,但是如果你的方法中的对象上有很多"switch"或"if/else",那么这可能表明你的设计有点"程序化"而你的对象只是价值桶.将逻辑移动到对象,调用对象上的方法,让他们决定如何响应.
我认为最好的方法是使用一个好的地图.使用字典,您几乎可以将任何输入映射到其他值/对象/函数.
你的代码看起来像这样(psuedo):
void InitMap(){ Map[key1] = Object/Action; Map[key2] = Object/Action; } Object/Action DoStuff(Object key){ return Map[key]; }
每个人都喜欢巨大的if else
积木.这么容易阅读!我很好奇你为什么要删除switch语句.如果需要switch语句,则可能需要switch语句.说真的,我会说这取决于代码的作用.如果所有开关都在调用函数(比如说),你可以传递函数指针.它是否是一个更好的解决方案是值得商榷的.
我认为语言也是一个重要因素.
我认为你所寻找的是战略模式.
这可以通过多种方式实施,这些方法已在此问题的其他答案中提及,例如:
值映射 - >函数
多态性.(对象的子类型将决定它如何处理特定进程).
一流的功能.
switch
如果您发现自己在语句中添加了新状态或新行为,则最好替换这些语句:
int状态 字符串getString(){ 开关(状态){ 案例0://状态0的行为 返回“零”; 情况1://状态1的行为 返回“一个”; } 抛出新的IllegalStateException(); } double getDouble(){ 切换(this.state){ 案例0://状态0的行为 返回0d; 情况1://状态1的行为 返回1天; } 抛出新的IllegalStateException(); }
添加新的行为需要复制switch
,并增加新的状态意味着添加另一case
对每一个 switch
发言。
在Java中,您只能切换数量非常有限的原始类型,这些原始类型的值在运行时知道。这本身就是一个问题:状态被表示为幻数或字符。
模式匹配和多个if - else
块都可以使用,尽管在添加新行为和新状态时确实存在相同的问题。
其他人建议的“多态性”解决方案是State模式的一个实例:
用自己的类替换每个状态。每个行为在类上都有自己的方法:
IState状态; 字符串getString(){ 返回state.getString(); } double getDouble(){ 返回state.getDouble(); }
每次添加新状态时,都必须添加IState
接口的新实现。在一个switch
世界中,您将为case
每个添加一个switch
。
每次添加新行为时,都需要向IState
接口和每个实现中添加新方法。尽管现在编译器将检查您是否在每个预先存在的状态上实现了新行为,但这和以前一样负担重。
其他人已经说过,这可能太重了,因此,当然有一点可以从一个位置移到另一个位置。就个人而言,我第二次编写开关是重构的关键。