当前位置:  开发笔记 > 编程语言 > 正文

消除代码切换的方法

如何解决《消除代码切换的方法》经验,为你挑选了8个好方法。

有什么方法可以消除代码中交换机的使用?



1> mlarsen..:

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();
}


-1:我从未使用带有`typeof`的switch语句,这个答案并没有提出在其他情况下解决switch语句的方法或理由.
我同意@Kevin - 给出的例子并没有真正展示如何通过多态来消除切换.简单的例子:通过切换它的值获取枚举的名称,或者在某种算法中通过适当的值执行一些代码.
由于类似的建议,我在http://stackoverflow.com/questions/374239/why-doesnt-python-have-a-switch-statement#374290中遭到类似的抨击,以至于很多人不相信多态性:)很好的例子。

2> toolkit..:

请参阅切换语句气味:

通常,类似的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 Map commandMap; // 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更容易理解和合乎逻辑.而且我通常非常喜欢OOP,但这个决议对我来说似乎太抽象了
只要您意识到多态解决方案牺牲了代码简单性,反对切换的参数就是有效的.此外,如果您始终将开关案例存储在枚举中,则某些编译器会警告您交换机中缺少状态.
感谢关于如何重构代码的好例子.虽然我可能会在开始时说它有点难以阅读(因为必须在几个文件之间切换以完全理解它)

3> Pop Catalin..:

switch是一种模式,无论是用switch语句实现的,if else链,查找表,oop多态,模式匹配还是其他.

您想要消除" switch statement "或" switch pattern "的使用吗?第一个可以被消除,第二个可以被消除,只有在可以使用另一个模式/算法时,并且大部分时间是不可能的,或者这不是更好的方法.

如果你想从代码中消除switch语句,首先要问的问题是消除switch语句和使用其他技术是有意义的.不幸的是,这个问题的答案是特定领域的.

请记住,编译器可以进行各种优化来切换语句.因此,例如,如果您想要有效地进行消息处理,那么切换语句几乎是可行的方法.但另一方面,基于switch语句运行业务规则可能不是最好的方法,应该重新构建应用程序.

以下是switch语句的一些替代方法:

查找表

多态性

模式匹配(特别用于函数式编程,C++模板)



4> Lars Westerg..:

切换本身并没有那么糟糕,但是如果你的方法中的对象上有很多"switch"或"if/else",那么这可能表明你的设计有点"程序化"而你的对象只是价值桶.将逻辑移动到对象,调用对象上的方法,让他们决定如何响应.



5> Josh..:

我认为最好的方法是使用一个好的地图.使用字典,您几乎可以将任何输入映射到其他值/对象/函数.

你的代码看起来像这样(psuedo):

void InitMap(){
    Map[key1] = Object/Action;
    Map[key2] = Object/Action;
}

Object/Action DoStuff(Object key){
    return Map[key];
}


取决于语言.与开关相比,它的可读性要低得多

6> Bernard..:

每个人都喜欢巨大的if else积木.这么容易阅读!我很好奇你为什么要删除switch语句.如果需要switch语句,则可能需要switch语句.说真的,我会说这取决于代码的作用.如果所有开关都在调用函数(比如说),你可以传递函数指针.它是否是一个更好的解决方案是值得商榷的.

我认为语言也是一个重要因素.


我假设那是讽刺:)

7> AJ...:

我认为你所寻找的是战略模式.

这可以通过多种方式实施,这些方法已在此问题的其他答案中提及,例如:

值映射 - >函数

多态性.(对象的子类型将决定它如何处理特定进程).

一流的功能.



8> jamesh..:

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接口和每个实现中添加新方法。尽管现在编译器将检查您是否在每个预先存在的状态上实现了新行为,但这和以前一样负担重。

其他人已经说过,这可能太重了,因此,当然有一点可以从一个位置移到另一个位置。就个人而言,我第二次编写开关是重构的关键。

推荐阅读
mobiledu2402852413
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有