重构嵌套切换到对象

时间:2012-05-09 07:57:46

标签: java design-patterns refactoring

我想对重构以下方法提出一些建议:

public boolean makeDecision(String group, int level, int primaryAmount, int secondaryAmount)
{
    if (group.equals("A"))
    {
        switch (level)
        {
            case 0 : return primaryAmount > 10000;break;
            case 1 : return primaryAmount > 20000;break;
            default : return secondaryAmount > 30000; break;
        }
    }
    else if (group.equals("B"))
    {
         switch (level)
         {
              case 0 : return primaryAmount > 40000;break;
              case 1 : return primaryAmount > 50000;break;
              default : return secondaryAmount > 60000; break;
         }

    }
    else if (group.equals("C"))
    {
        switch(level)
        {
            case 0 : return primaryAmount > 70000;break;
            case 1 : return primaryAmount > 80000;break;
            default : return secondaryAmount > 90000; break;
        }

    }
    return false;
} 

我想要实现的目标:

  • 允许代码遵循开放/封闭原则,因为会有更多的组/级别及时。
  • 删除'level'witch语句中的重复项。
  • 理想情况下,删除“组”顶级切换语句。

2 个答案:

答案 0 :(得分:1)

由于每个案例都是通过一个简单的比较来计算的,你也可以用任何一种方式进行所有的比较。

所以这是一个建议:

boolean[] aSol = { primary > 10000, primary > 20000, secondary > 30000 };
boolean[] bSol = { primary > 40000, primary > 50000, secondary > 60000 };
boolean[] cSol = { primary > 70000, primary > 80000, secondary > 90000 };

level = Math.min(level, 2);
return group.equals("A") ? aSol[level] :
       group.equals("B") ? bSol[level] :
       group.equals("C") ? cSol[level] :
       false;

我认为它具有相当的可读性和可维护性。

这是另一个略有不同的表述:

boolean[][] result = {
        { primary > 10000, primary > 20000, secondary > 30000 },
        { primary > 40000, primary > 50000, secondary > 60000 },
        { primary > 70000, primary > 80000, secondary > 90000 } };

int groupId = Arrays.asList("A", "B", "C").indexOf(group);

if (groupId == -1)
    return false;

boolean[] groupResult = result[groupId];
return groupResult[Math.min(level, groupResult.length-1)];

另一个选择是使用方法

创建一个接口
makeDecision(int level, int primaryAmount, int secondaryAmount)

然后使用决策程序

填充Map<String, GroupDecision>
groupMap.put("A", new GroupDecision() { ... });
groupMap.put("B", new GroupDecision() { ... });
groupMap.put("C", new GroupDecision() { ... });

然后致电

return groupMap.get(group).makeDecision(level, primaryAmount, secondaryAmount);

这种方法可能是最具扩展性和可读性的方法。

答案 1 :(得分:1)

群组看起来像是有行为。您可以将字符串组提升为第一类类型。您还可以在类上放置方法来表示您已获得的逻辑。我已经在变量上添加了愚蠢的名字,他们可以做得更好。

public class Group {
    public static Group A = new Group(10000,20000,30000);
    public static Group B = new Group(40000,50000,60000);
    public static Group C = new Group(70000,80000,90000);

    private int primaryMin;
    private int primaryMid;
    private int secondaryMax;

    private Group(int min, int mid, int max) {
        primaryMin = min;
        primaryMid = mid;
        secondaryMax = max;
    }

    public boolean getLevel(int level, int primaryAmount, int secondaryAmount) {
       if (level == 0)
         return primaryAmount > primaryMin;
       else if (level == 1) 
         return primaryAmount > primaryMid;
       else 
         return secondaryAmount > secondaryMax;
    }
}

所以现在你可以将你的顶级声明降低到

public boolean makeDecision(Group group, int level, int primaryAmount, int secondaryAmount) {
  return group.getLevel(level, primaryAmount, secondaryAmount);
}

您可以考虑使用null object pattern来处理未知群组。

如果你说级别会及时增长,那么我会考虑再次做同样的事情来引入Level类并将if / else链作为另一层的polymorpshim推送到那里。然后,这将成为double dispatch pattern,首先是Group的类型,然后是Level的类型。这意味着您可以添加新代码而无需修改现有代码。