Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 避免代码重复——最佳方法_Java_Design Patterns - Fatal编程技术网

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