如何在其他if-else中消除if-else具有相同条件但不同的动作?

时间:2017-12-06 05:40:27

标签: java if-statement

假设我有以下代码:

int age=(from user input);
int weight=(from user input);

if(age>60){
    if(weight>100){
        function1();
    }else if(weight<40){
        function2();
    }else{
        function3();
    }
}else if(age<20){
    if(weight>100){
        function4();
    }else if(weight<40){
        function5();
    }else{
        function6();
    }
}else{
    if(weight>100){
        function7();
    }else if(weight<40){
        function8();
    }else{
        function9();
    }
}

问题在于代码模式:

if(weight>100){
    //do something different
}else if(weight<40){
    //do something different
}else{
    //do something different
}

重复,因为有不同的年龄范围。并且我不能将内部if-else包含在单个函数中,因为要做的事情是不同的,即使条件是相同的。有没有办法修改这段代码,以便代码模式:

if(age>60){
    //do something different
}else if(age<20){
    //do something different
}else{
    //do something different
}

if(weight>100){
    //do something different
}else if(weight<40){
    //do something different
}else{
    //do something different
}

只会出现一次?

5 个答案:

答案 0 :(得分:1)

没有看到你的所有函数1-9做什么(这可能是Stack Overflow的代码太多了),很难给出明确的答案。如果function1function2function3age > 60function1function4function7时都做了一些常见的事情在weight > 100时,所有人都会做一些常见的事情,然后你可以将这些功能分开,然后将公共部分重新组合成新的方法。

如果你真的有9个不同的功能没有任何共同点,那么就没有真正好的解决方案。您可以尝试设置将所有9种组合映射到函数的地图:

Map<String, Runnable> functions = new HashMap<>();
functions.put("senior_heavy") = this::function1;
functions.put("senior_medium") = this::function2;
functions.put("senior_light") = this::function3;
functions.put("middleaged_heavy") = this::function4;
...
functions.put("child_light") = this::function9;

[你必须考虑更好的名字,因为一个20岁的孩子并不完全中年。]

然后:

String ageString;
// set this to "senior", "middleaged", or "child"
String weightString;
// set this to "heavy", "medium", or "light"

functions.get(ageString + "_" + weightString).run();

Runnable是不带参数且不返回结果的方法的接口。 (对于带参数和/或返回结果的函数,还有其他功能接口类型可供使用。或者您可以在smac89的答案中定义自己的类型,这样可以为功能接口类型提供更具描述性的名称。 )this::function1是对属于当前对象function1的{​​{1}}的引用;如果thisfunction1,则需要说static

这将消除重复的ThisClass::function1模式,但这不是一个漂亮的解决方案。如果我正在审查您的代码,我不会抱怨您的原始代码,因为替代方案也不是很好。 (if的二维数组是另一种选择。)

答案 1 :(得分:1)

不是特别优雅。简而言之,构成一个执行内部条件检查的方法,并允许在不同情况下传递“动作”

// Change to use other proper functional interface.  Using Runnable
// just to align with your sample code.
doOnWeight(int weight, 
           Runnable overWeightAction,
           Runnable normalWeightAction,                       
           Runnable underWeightAction) {
    if(weight>100){
        overWeightAction.apply();
    }else if(weight<40){
        underWeightAction.apply();
    }else{
        normalWeightAction.apply();
    }
}    
//.......

// your original code, I assume your functions are instance methods
if(age>60){
    doOnWeight(weight, this::function1, this::function3, this::function2)
}else if(age<20){
    doOnWeight(weight, this::function4, this::function6, this::function5)
}else{
    doOnWeight(weight, this::function7, this::function9, this::function8)
}

答案 2 :(得分:1)

public class User {
    int age;
    int weight;
}

@FunctionalInterface
public interface WeightFunction {
    void perform(User user);
}

@FunctionalInterface
public interface AgeFunction {

    WeightFunction getWeightFunction(User user);
}

public class Age60Function implements AgeFunction {
    @Override
    public WeightFunction getWeightFunction(User user) {
        String desc = "Age 60 ";
        if (user.weight > 100) {
            return weightUser -> System.out.println(desc + "Age > 100");
        } else if (user.weight < 40) {
            return weightUser -> System.out.println(desc + "Age < 40");
        }
        return weightUser -> System.out.println(desc + "100 > Age > 40");
    }

}

然后你可以创建外部if和创建相关的AgeFunction并执行该功能。

另一个建议如果重量类别不等于所有年龄限制,因为此示例重量类别100 +,40-和100>年龄> 40,您可以按照以下实施。

public interface AdvanceAgeFunction {
    WeightFunction get100PlusWeightFunction(User user);
    WeightFunction get40MinusWeightFunction(User user);
    WeightFunction getWeightFunction(User user);
} 

答案 3 :(得分:0)

我能想到的最好的就是:

interface WeightFunc {
    void function();
}

public static final List<WeightFunc> weightFuncs = Arrays.asList(weightFunc1, weightFunc2,...);

现在在你的方法中

List<WeightFunc> choices = null;

if(age>60){
    choices = Arrays.asList(weightFuncs.get(0), weightFuncs.get(1), ...);
    // 1, 2, 3
}else if(age<20){
    choices = Arrays.asList(weightFuncs.get(3), weightFuncs.get(4), ...);
    // 4, 5, 6
}else{
    choices = Arrays.asList(weightFuncs.get(6), weightFuncs.get(7), ...);
    // 7, 8, 9
}

WeightFunc choice = null;

if(weight>100){
    choice = choices.get(0);
    //do something different
}else if(weight<40){
    choice = choices.get(1);
    //do something different
}else{
    choice = choices.get(2);
    //do something different
}

现在打电话给:

choice.function();

IMO,我更喜欢你的初始方法

答案 4 :(得分:0)

我没有完全明白你的问题,但从我看到的情况来看,似乎你不会丢失冗余代码,所以这就是我的建议。

创建临时变量假设

int ageGroup;

和计算权重计算的函数,其中ageGroup作为参数传递

void CheckWeight(int ageGroup)
{
}

您可以通过创建另一个功能来进一步减少冗余代码,以管理在切换条件下在功能1-9中完成的工作。

您的最终代码块将如下所示:

if(age>60){
    CheckWeight(1);
}else if(age<20){
    CheckWeight(2)
}else{
    CheckWeight(3)
}



void CheckWeight(int ageGroup)
{
    if(weight>100){
       Compute(ageGroup,1);
    }else if(weight<40){
       Compute(ageGroup,2);
    }else{
       Compute(ageGroup,3);
    }
}


void Compute(int ageGroup,int weightGroup)
{
    switch(ageGroup)
    {
        case 1: 
            switch(weightGroup)
            {
                case 1:
                    //func1;
                    break;
                case 2:
                    //func 2;
                    break;
                .
                .
            }    
            break;
       case 2:
       .
       .
       .
    }
}

这是我能想到的最好的,可能还有其他实现。