我有两个方法,它们具有相同的列表和参数类型,几乎相同的主体,但每个方法都调用另一个函数来获取元素列表。更确切地说:
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)
}
所以有些变量是本地变量,有些变量是通过参数传递的。
答案 0 :(得分: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
}
答案 1 :(得分: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
个案。
答案 2 :(得分:3)
在ListSource类/接口中封装service.getListA或service.getListB的调用,在具体类中实现每个版本,并将具体实例作为第三个参数传递。这基本上是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)
}
答案 3 :(得分: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程序员,所以你必须read the docs)
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)
}
答案 4 :(得分: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相同。
答案 5 :(得分:-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) });
}