简体   繁体   English

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

[英]How to avoid same logic in two functions.

I want to not repeat a specific piece of code and need advice on how to structure it better 我不想重复特定的代码,并且需要有关如何更好地构建代码的建议

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

I'd like to able to consolidate the logic in getTabName() and getUserCount() methods. 我希望能够合并getTabName()getUserCount()方法中的逻辑。

Having switch statements checking for the same thing doesn't seem efficient, but they are returning two different things.... 用switch语句检查同一件事似乎并不高效,但是它们返回的是两种不同的事情。

The only solution I can think of, which is balanced between simple and not overengineered (as greatly highlighted in one of the comments) is: 我能想到的唯一解决方案是在简单和过度设计之间取得平衡(在其中一项注释中得到了极大的强调):

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

and you use it like this: 您可以像这样使用它:

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

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

The only problem with this approach is that all arguments are evaluated eagerly, which is not a problem in your case, but might be in others. 这种方法的唯一问题是,所有参数都经过热切评估,这对您而言不是问题,但在其他情况下也可能如此。

Here is an example using enum to do the dirty work: 这是一个使用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));
    }
}

I would use a Java enum instead of static int s and switch clauses. 我将使用Java enum代替static intswitch子句。 The good thing about enums is that you constrain the values to be exactly those you declare. 枚举的好处是您可以将值约束为声明的值。

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

Also worth looking at the enums docs at Oracle 同样值得一看的Oracle枚举文档

use enums like this: 使用这样的枚举:

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

Create an interface or abstract class for the common aspects of a tab and then use implementation classes for each. 为选项卡的常见方面创建一个接口或抽象类,然后为每个方面使用实现类。 In psuedo-code: 在伪代码中:

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

You can use enums to maintain a list of them, but be careful with putting implementation logic in an enum. 您可以使用枚举来维护它们的列表,但是在将实现逻辑放入枚举时要小心。

use an enum that as a CTOR for each of its values takes the values you need (like the "TA" ,...) , store it within the CTOR , and use a method return this value . 使用一个枚举,作为其每个值的CTOR接受所需的值(例如“ TA”,...),将其存储在CTOR中,并使用方法返回此值。

this way you don't need to use the switch. 这样,您无需使用开关。

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

Better to use a bean class and add attributes/operations for access and mutating to that class. 最好使用bean类,并添加属性/操作来访问和更改该类。 You can do Constructor Injection or Setter Injection, I prefer Setter Injection which decouples my code from bean. 您可以执行构造函数注入或Setter注入,我更喜欢Setter Injection,它将我的代码与Bean分离。

And write a method which returns a Bean, in switch set the values in the bean and return bean. 并编写一个返回Bean的方法,在开关中设置Bean中的值并返回Bean。 By which you are actually maintaining your code in one place and all the data together. 通过它,您实际上将代码保存在一个地方,而所有数据都保存在了一起。 On my view this is the simplest solution. 我认为这是最简单的解决方案。 Hope this helps you. 希望这对您有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 JPA和聚合函数。 如何使用查询结果? - JPA and aggregate functions. How do I use the result of the query? 如何避免同时工作两个JButton - How to avoid to work two JButton at the same time 如何在相同条件下调用两个不同的函数? - How to call two different functions for a same condition? 如何避免在Quartz中同时运行两个作业? - How to avoid two jobs running at the same time in Quartz? 如何避免来自两个 pod 的相同事件触发 - How to avoid same event trigger from two pods 如何使用相同的逻辑替换两个文件中出现的相同“词干”的数字? - How to replace numbers with same 'stem' that occur in two files using same logic? 我们如何让两个线程(可以访问相同的共享实例 obj)执行不同的逻辑? - How can we have two threads (having access to same shared instance obj) perform different logic? Setter和Getter功能。 在Android中。 性能开销? - Setter and Getter functions. In Android. Performance overhead? 声明类veriable(列表)或将其发送给许多函数。 什么是更好的? - Declare class veriable (List) or send it to many functions. what is better? 在具有相同逻辑的两个应用程序中采样相同的100万条记录 - sample same 1 million records in two applications with same logic
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM