5

同じリストと引数の型、ほぼ同じ本体を持つ 2 つのメソッドがありますが、それぞれが別の関数を呼び出して要素のリストをフェッチします。より正確には:



    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

あなたのケースでコードの重複を避ける1つの方法は、リストを取得する方法が使用されるかを決定するために使用される追加のパラメータを導入することです:

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を定義します。defaultswitch

于 2013-01-16T23:01:23.517 に答える
3

service.getListA または service.getListB の呼び出しを ListSource クラス/インターフェースにカプセル化し、各バージョンを具体的なクラスに実装し、具体的なインスタンスを 3 番目の引数として渡します。これは基本的に、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が、順序が混乱したり、outer を見逃したり、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 に答える