2013-01-16 162 views
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) 
     } 

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

UPDATE:



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

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

+2

通过你'列出'作为一个参数的单个函数并包装它? – fge

+4

c,d和e字段还是它们在这些方法中的局部变量? –

+1

你可以重写你的例子,以便编译或至少使用正确的语法吗? –

回答

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 
} 
+5

仍然会有代码重复,以这种方式调用这两种方法本身就是代码重复......我认为OP是在设计模式方法之后。 – amit

+0

@amit我同意,但是更多的面向对象方法需要更多的代码行,然后是上面的少量重复。即使使用case语句也会引入相同数量的行......当然,这取决于用例,因为面向对象的方法在将来可能更具可扩展性。 –

+0

@ dicarlo2:采用这种方法,您需要为每种情况提供一种新方法。通过我的回答中的方法,您还可以将列表选择代码放入枚举中并摆脱'switch'语句。这意味着,只需要在枚举中添加更多可能性,并且代码复制将完全消除。 – jlordo

4

的一种方法是引入用来决定要检索的方法列表将要使用一个额外的参数:

​​

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

+0

+1清理并免费复制代码。请将int方法替换为一个枚举,以使它更好。 – amit

+0

@amit:看到我的编辑,希望推出的代码,然后写我的评论;) – jlordo

+0

那么怎么样,包括“法取”在枚举部分摆脱开关? – assylias

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) 
} 
+1

或'名单的GetList(INT参数... args);' – assylias

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

的thelist事先不知道...... – assylias

+0

哪里有OP陈述变量c,d,e是局部派生的? @assylias –

+2

@PaulSullivan这暗示了它们不是方法参数列表的一部分。 –

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相同,只是形式不同。

+0

'getList()'返回类型'void'?此外,我将摆脱'MyClass'并将使用'int ...'作为该方法的参数。 – jlordo

+0

@jlordo固定,也使用一个额外的类屏蔽'getList'方法进一步的变化。假设你需要稍后在'METHOD_5'中添加一个'double',它将需要'MyClass'中的一个额外字段,并且对原始方法进行最小的改变,而不是改变每个'getList'。 –

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

,如果你关心new您可以使用枚举代替GetObjects,但不要”不介意让订单混在一起,错过了外部this,不想打开它(尽管它可以实现公共接口)。

可能会出现Java SE 8中更好的语法。 IIRC,沿线:

public void method1(int a, int b) { 
    impl(a, b, { -> service.getListA(c, d) }); 
} 
+1

'c','d'和'e'从哪里来? –

+0

@ dicarlo2我以为他们是田地。如果他们是本地人,那么你有选择:添加更多的参数,引入一个新的(有希望有趣的)对象,等等。 –

+1

根据这个假设,它看起来有点过于复杂,而只是将列表作为参数传递...... – assylias