Java 避免代码重复——最佳方法
我有两个方法,它们具有相同的列表和参数类型以及几乎相同的主体,但它们每个都调用另一个函数来获取元素列表。更准确地说:Java 避免代码重复——最佳方法,java,design-patterns,Java,Design Patterns,我有两个方法,它们具有相同的列表和参数类型以及几乎相同的主体,但它们每个都调用另一个函数来获取元素列表。更准确地说: 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
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)
}
公共无效方法1(内部a、内部b){
//主体(两种方法相同)
List=service.getListA(int c,int d);
//身体的其余部分(两种方法相同)
}
公共无效方法2(内部a、内部b){
//主体(两种方法相同)
List=service.getListB(intc,intd,inte);
//身体的其余部分(两种方法相同)
}
在这种情况下,避免代码重复的最佳方法是什么?我考虑过策略模式,但在参数列表中有一个不同的问题
更新:
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)
}
公共无效方法1(内部a、内部b){
//主体(两种方法相同)
int c=某个_值;
List=service.getListA(a,b,c);
//身体的其余部分(两种方法相同)
}
公共无效方法2(内部a、内部b){
//主体(两种方法相同)
int c=某个_值;
int d=另一个_值;
List=service.getListB(a,b,c,d);
//身体的其余部分(两种方法相同)
}
所以有些变量是局部变量,有些是通过参数传递的。将它们分解成其他方法
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(内部a、内部b){
MyClass MyClass=方法3(a,b);
List=service.getListA(myClass.getC(),myClass.getD());
方法4(列表);
}
公共无效方法2(内部a、内部b){
MyClass MyClass=方法3(a,b);
List List=service.getListB(myClass.getC(),myClass.getD(),myClass.getE());
方法4(列表);
}
公共MyClass{
私人终审法院;
非公开期末考试;
私人终审法院;
...
}
公共MyClass方法3(int a,int b){
//身体
返回新的MyClass(c、d、e)
}
公共作废方法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)
}
public void方法(int a、int b、int方法){
//主体(两种方法相同)
List=null;
开关(方法){
案例1:
list=service.getListA(int c,int d);
打破
案例2:
list=service.getListB(int c,int d,int e);
打破
}
//身体的其余部分(两种方法相同)
}
我不使用
int method
作为附加参数,而是使用一个新的enum
类型,并在switch
语句中定义一个default
大小写。在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)
}
接口列表源{
List getList(int c、int d、int e);
}
类ListSourceA实现ListSource{
//建造师等。
@凌驾
公共getList(intc、intd、inte){
返回服务.getListB(c,d);
}
}
类ListSourceB实现ListSource{
//建造师等。
@凌驾
公共getList(intc、intd、inte){
返回服务.getListA(c,d,e);
}
}
公共void方法(inta、intb、ListSource){
//主体(两种方法相同)
List=source.getList(intc,intd,inte);
//身体的其余部分(两种方法相同)
}
公共作废方法(int a、int b、列表){
//主体(两种方法相同)
列表=列表;
//身体的其余部分(两种方法相同)
}
对我来说,这消除了所有代码重复,意味着每次我们想要对使用不同方法签名派生的列表进行操作时,都不必修改该方法
我相信,如果使用泛型不知道SomeObject的类型,您可以进一步了解这一点(我不是java程序员,所以您必须这样做)
public void方法(inta、intb、列表){
//主体(两种方法相同)
列表=列表;
//身体的其余部分(两种方法相同)
}
您还可以使用枚举:
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;
...
}
public void方法(inta、intb、Service){
//身体
列表=service.getList(myClass);
//休息
}
公共枚举服务{
方法1{
@凌驾
公共列表getList(MyClass MyClass){}
},
方法2{
@凌驾
公共列表getList(MyClass MyClass){}
};
公共摘要列表getList(MyClass MyClass);
}
公共MyClass{
私人终审法院;
非公开期末考试;
私人终审法院;
...
}
基本上与@proskor相同,只是形式不同。如果身体各部分相互依赖,因此您无法按照@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)
}
将
List
作为参数传递给单个函数并将其包装?这些方法中是c、d和e字段还是局部变量?能否重写示例以使其编译或至少使用正确的语法?我想重申@DonRoby关于c、d、e是局部生成的(在方法内部)的问题或全球/外部生成。这对问题很重要,仍然会有代码重复,以这种方式调用这两个方法本身就是代码重复。。。我认为OP采用的是设计模式方法。@amit我同意,但是更多的OO方法需要更多的代码行,而不是上面的少量重复。即使使用case语句也会引入相同数量的行。。。当然,这取决于用例,因为OO方法可能更具扩展性
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;
...
}
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)
}
public void method1(int a, int b) {
impl(a, b, { -> service.getListA(c, d) });
}