如何在两个函数中避免相同的逻辑。

时间:2012-07-16 19:32:34

标签: java

我不想重复一段特定的代码,并且需要有关如何更好地构建代码的建议

public static final int TAB_A= 0;
public static final int TAB_B= 2;
public static final int TAB_C= 3;
public static final int NO_TAB = -1;

public String getTabName() {
    switch (getTabId()) {
        case TAB_A:
            return "TA";
        case TAB_B:
            return "TB";
        case TAB_C:
            return "TC";
        default:
            return "NT";
    }
}

public string execute() {  
  setResults(getTabName());
}

public int getUserCount() {
    SomeVO vo = (SomeVO) getFirstResultSet().get(0);
    switch (getTabId()) {
        case TAB_A:
            return vo.getTabAResults();
        case TAB_B:
            return vo.getTabBResults();
        case TAB_C:
            return vo.getTabCResults();
        default:
            return vo.getSomeStuff();
    }        
}  

我希望能够合并getTabName()getUserCount()方法中的逻辑。

让switch语句检查相同的东西似乎效率不高,但它们返回了两个不同的东西......

7 个答案:

答案 0 :(得分:3)

我能想到的唯一解决方案是在简单和非过度工程之间取得平衡(正如其中一条评论中强调的那样):

private <T> T mapFromTabId(T a, T b, T c, T def) {
    switch (getTabId()) {
        case TAB_A:
            return a;
        case TAB_B:
            return b;
        case TAB_C:
            return c;
        default:
            return def;
    }
}

你可以这样使用它:

public String getTabName() {
    return mapFromTabId("TA", "TB", "TC", "NT");
}

public int getUserCount() {
    return mapFromTabId(vo.getTabAResults(), vo.getTabBResults(), vo.getTabCResults(), vo.getSomeStuff());
}

这种方法的唯一问题是所有参数都是热切评估的,这在您的情况下不是问题,但可能在其他情况下。

答案 1 :(得分:2)

以下是使用enum执行脏工作的示例:

import java.lang.reflect.Method;

public class Test {

    public enum TABS {
        TAB_A("TA", "getTabAResults"),
        TAB_B("TB", "getTabBResults"),
        TAB_C("TC", "getTabCResults"),
        NO_TAB("NT", "getSomeStuff");

        private String name, method;

        private TABS(String name, String method) {
            this.name = name;
            this.method = method;
        }

        public String getName() {
            return name;
        }

        public int getResults(SomeVO vo) {
            int result = -1;
            try {
                Method m = vo.getClass().getMethod(method);
                result = (Integer) m.invoke(vo, (Object[]) null);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            return result;
        }
    }

    static class SomeVO {
        public int getTabAResults() {
            return 1;
        }

        public int getTabBResults() {
            return 2;
        }

        public int getTabCResults() {
            return 3;
        }

        public int getSomeStuff() {
            return 4;
        }
    }

    public static void main(String[] args) {
        SomeVO someVO = new SomeVO();
        System.out.println(TABS.TAB_A.getName() + " is "
                + TABS.TAB_A.getResults(someVO));
        System.out.println(TABS.TAB_B.getName() + " is "
                + TABS.TAB_B.getResults(someVO));
        System.out.println(TABS.TAB_C.getName() + " is "
                + TABS.TAB_C.getResults(someVO));
        System.out.println(TABS.NO_TAB.getName() + " is "
                + TABS.NO_TAB.getResults(someVO));
    }
}

答案 2 :(得分:1)

我会使用Java enum而不是static intswitch子句。枚举的好处在于您将值限制为您声明的值。

public enum AnEnum {
    VAL_A {
        public String getName() { return "A"; }
        public int getResult(Thing t) { return t.getResultsA(); }
    };

    public abstract String getName();
    public abstract int getResult(Thing t);
}

另外值得查看Oracle

上的枚举文档

答案 3 :(得分:1)

使用这样的枚举:

public static enum TableType {

    TAB_A(0, "TA"){
        private int _getUserCound(SomeVO vo){
            return vo.getTabAResults();
        }
    },
    TAB_B(2, "TB"){
        private int _getUserCound(SomeVO vo){
            return vo.getTabBResults();
        }
    },
    TAB_C(3, "TC"){
        private int _getUserCound(SomeVO vo){
            return vo.getTabCResults();
        }
    },
    NO_TAB(-1, "NT"){
        private int _getUserCound(SomeVO vo){
            return vo.getSomeStuff();
        }
    };

    int id;
    String name;
    private TableType(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    private abstract int _getUserCound(SomeVO vo);

    public int getUserCount(){
        SomeVO vo = (SomeVO) getFirstResultSet().get(0);
        return _getUserCound(vo);
    }

    public static TableType fromId(int id){
        for (TableType v : values()){
            if (v.getId() == id) return v;
        }
        return NO_TAB;
    }

}

public String getTabName() {
    return TableType.fromId(getTabId()).getName();
}

public string execute() {
    setResults(getTabName());
}

public int getUserCount() {
    return TableType.fromId(getTabId()).getUserCount();
}

答案 4 :(得分:1)

为选项卡的常见方面创建接口或抽象类,然后为每个选项使用实现类。在伪代码中:

public abstract class Tab {
    public abstract String getTabName();
    public abstract int getUserCount();

    // ...
}

public final class TabA extends Tab {
    private static final String NAME = "TA";

    // ...

    @Override
    public String getTabName() {
        return NAME;
    }

    @Override
    public int getUserCount() {
      SomeVO vo = (SomeVO)getFirstResultSet().get(0);
      return vo.getResults();
    }
}

您可以使用枚举来维护它们的列表,但要小心将实现逻辑放在枚举中。

答案 5 :(得分:0)

使用枚举,作为每个值的CTOR获取所需的值(如“TA”,...),将其存储在CTOR中,并使用方法返回此值。

这样您就不需要使用开关了。

链接: http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html

答案 6 :(得分:0)

最好使用bean类并添加属性/操作以访问和变异到该类。你可以做Constructor Injection或Setter Injection,我更喜欢Setter Injection,它将我的代码与bean分离。

并编写一个返回Bean的方法,在switch中设置bean中的值并返回bean。 您实际上将代码保存在一个地方并将所有数据保存在一起。 在我看来,这是最简单的解决方案。希望这会对你有所帮助。