摆脱switch-case块

时间:2017-12-11 18:42:15

标签: java if-statement design-patterns switch-statement object-oriented-analysis

如何将此switch-case块转换为良好的代码?

private static void agentFieldContructor(Agent agent, String nodeName, String value) {

    switch (nodeName) {

        case "Description":
            agent.setDescription(value);
            break;

        case "Model":
            agent.setModel(value);
            break;

        (... +18)

    }

}

agent是一个对象,我根据指定的value使用nodeName参数填充它。
每个nodeName引用一个不同的代理属性,但我收到它就像一个字符串,我不能改变它。我搜索了一些设计模式但找不到任何可以帮助我的东西。

5 个答案:

答案 0 :(得分:1)

如果允许您使用反射。

private static void agentFieldContructor(Agent agent, String nodeName, String value) {
    Method setMethod =  Agent.class.getMethod("set"+nodeName,String.class)
    setMethod.invoke(Agent,value)
}

答案 1 :(得分:1)

实现这一目标的一个紧凑方法是通过反思。您可以访问setter方法并使用您的值调用它。

    0  1  2
d1  1  1  1
d2  2  2  2
d3  3  3  3

请注意,您将不得不处理:

  • 如果插入无效的节点名称会发生​​什么?
  • 如果值是意外值(如public static void agentFieldConstructor(Agent agent, String nodeName, String value) { try { agent.getClass().getDeclaredMethod("set" + nodeName, value.getClass()).invoke(agent, value); } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { e.printStackTrace(); } }
  • ,会发生什么
  • 处理混合大小写节点名称(现在,如果第一个字母大写,则此方法有效)
  • 处理非标准节点名称(这将假定大部分是JavaBean命名约定)

......所有这些都是读者的练习。

答案 2 :(得分:1)

没有switch-case或反射的另一种可能性是使用复杂的枚举。这里的枚举是转换器,从String键到setter调用:

public enum AgentFields {
    DESCRIPTION {
        @Override
        public void setInAgent(Agent agent, String value) {
            agent.setDescription(value);
        }
    },

    MODEL {
        @Override
        public void setInAgent(Agent agent, String value) {
            agent.setModel(value);
        }
    };

    public abstract void setInAgent(Agent agent, String value);

    // Call this method to set a named field's value
    public static void agentFieldSetter(Agent agent, String nodeName, String value) {
        AgentFields.valueOf(nodeName.toUpperCase()).setInAgent(agent, value);
    }

}

这声明了一个枚举,每个字段有一个“值”,每个值带有一个单独的setter。使用所有枚举自动提供的valueOf()方法完成调度。我用toUpperCase修饰它以允许通常的大写枚举值约定,并使它不区分大小写。

答案 3 :(得分:0)

这里的问题不在于switch-case语句本身。而是与Agent类本身的设计有关。首先,Agent应该有一个合适的构造函数,您可以在其中传递属性值。如果这些值可以改变,那么Agent的用户应该直接调用setter而不是使用这个帮助函数。

更重要的是,具有20个属性的类可能是重构的候选者。尝试找到这些属性的子集之间的关系,这些属性可以分解为单独的类。

答案 4 :(得分:0)

我完全同意评论。但是,如果您真的不想使用switch case并且您的方法名称和案例字符串几乎相同,则可以使用反射。 Here是可以帮助您的解决方案。