5

我有两个方法具有相同的列表和参数类型以及几乎相同的主体,但它们中的每一个都调用另一个函数来获取元素列表。更准确地说:



    public void method1 (int a, int b) {
            //body (the same in both of methods)
            List<SomeObject> list = service.getListA(int c, int d);
            //rest of the body (the same in both of methods)
        }

        public void method2 (int a, int b) {
            //body (the same in both of methods)
            List<SomeObject> list = service.getListB(int c, int d, int e);
            //rest of the body (the same in both of methods)
        }

在这种情况下,避免代码重复问题的最佳方法是什么?我考虑了策略模式,但参数列表存在差异。

更新:



    public void method1 (int a, int b) {
            //body (the same in both of methods)
            int c = some_value;
            List<SomeObject> list = service.getListA(a, b, c);
            //rest of the body (the same in both of methods)
        }

        public void method2 (int a, int b) {
            //body (the same in both of methods)
            int c = some_value;
            int d = another_value;
            List<SomeObject> list = service.getListB(a, b, c, d);
            //rest of the body (the same in both of methods)
        }

所以有些变量是本地的,有些是通过参数传递的。

4

6 回答 6

6

将它们分解为其他方法。

public void method1 (int a, int b) {
        MyClass myClass = method3(a, b);
        List<SomeObject> list = service.getListA(myClass.getC(), myClass.getD());
        method4(list);
}

public void method2 (int a, int b) {
        MyClass myClass = method3(a, b);
        List<SomeObject> list = service.getListB(myClass.getC(), myClass.getD(), myClass.getE());
        method4(list);
}

public MyClass {
    private final int c;
    private final int d;
    private final int e;
    ...
}

public MyClass method3(int a, int b) {
    // body
    return new MyClass(c, d, e)
}

public void method4(List<SomeObject> list) {
    // rest of body
}
于 2013-01-16T22:57:33.293 回答
4

在您的情况下避免代码重复的一种方法可能是引入一个额外的参数,该参数用于决定将使用哪种方法来检索列表:

public void method (int a, int b, int method) {
    //body (the same in both of methods)
    List<SomeObject> list = null;
    switch (method) {
        case 1: 
            list = service.getListA(int c, int d);
            break;
        case 2: 
            list = service.getListB(int c, int d, int e);
            break;
    }
    //rest of the body (the same in both of methods)
}

int method我将使用新enum类型并在语句中定义一个default案例,而不是用作附加参数。switch

于 2013-01-16T23:01:23.517 回答
3

将 service.getListA 或 service.getListB 的调用封装在 ListSource 类/接口中,在具体类中实现每个版本,并将具体实例作为第三个参数传递。这基本上是 jlordo 提出的答案的面向对象版本。

interface ListSource {
    List<SomeObject> getList(int c, int d, int e);
}

class ListSourceA implements ListSource {
    // constructor etc.
    @Override
    public getList(int c, int d, int e) {
      return service.getListB(c, d);
    }
}

class ListSourceB implements ListSource {
    // constructor etc.
    @Override
    public getList(int c, int d, int e) {
      return service.getListA(c, d, e);
    }
}

public void method (int a, int b, ListSource source) {
    //body (the same in both of methods)
    List<SomeObject> list = source.getList(int c, int d, int e);
    //rest of the body (the same in both of methods)
}
于 2013-01-16T23:12:33.570 回答
0
public void method (int a, int b, List<SomeObject> theList) {
    //body (the same in both of methods)
    List<SomeObject> list = theList;
    //rest of the body (the same in both of methods)
}

这对我来说消除了所有代码重复,这意味着每次我们想要对使用不同方法签名派生的列表进行操作时都不必修改方法。

如果使用泛型不知道 SomeObject 类型,我相信你可以进一步这样做(而且我不是 java 程序员,所以你必须阅读文档

public void method (int a, int b, List<T> theList) {
    //body (the same in both of methods)
    List<T> list = theList;
    //rest of the body (the same in both of methods)
}
于 2013-01-16T23:14:12.040 回答
0

您还可以使用枚举:

public void method(int a, int b, Service service) {
    // body
    List<SomeObject> list = service.getList(myClass);
    // rest
}

public enum Service {
    METHOD_1 {
        @Override
        public List<SomeObject> getList(MyClass myClass) {}
    },
    METHOD_2 {
        @Override
        public List<SomeObject> getList(MyClass myClass) {}
    };

    public abstract List<SomeObject> getList(MyClass myClass);
}

public MyClass {
    private final int c;
    private final int d;
    private final int e;
    ...
}

本质上与@proskor 相同,只是形式不同。

于 2013-01-16T23:15:45.137 回答
-1

如果身体部位相互依赖,那么你不能像@dicarlo2 的回答那样做:

private interface GetObjects {
    List<SomeObject> get();
}

public void method1(int a, int b) {
    impl(a, b, new GetObjects() { public List<SomeObject> get() {
        return service.getListA(c, d);
    }});
}

public void method2(int a, int b) {
    impl(a, b, new GetObjects() { public List<SomeObject> get() {
        return service.getListB(c, d, e);
    }});
}

private void impl(int a, int b, GetObjects getObjects) {
    //body (the same in both of methods)
    List<SomeObject> list = getObjects.get();
    //rest of the body (the same in both of methods)
}

GetObjects如果您担心,您可以使用枚举代替new,但不介意将顺序混淆,错过外部this并且不想打开它(尽管它可以实现公共接口)。

Java SE 8 中可能会出现更好的语法。IIRC,大致如下:

public void method1(int a, int b) {
    impl(a, b, { -> service.getListA(c, d) });
}
于 2013-01-16T23:20:51.443 回答