2017-03-25 12 views
1

時にはメソッドがボディの中央にある唯一の違いを持ち、一般化したり、コードの共通部分を単一のメソッドに抽出することは困難です。リファクタリングオーバーライドメソッドは、ボディの中央にのみ差があります。

質問自体:forループボディのコードが重複しないように、次のインターフェイスメソッドの実装をどのようにリファクタリングしますか?

interface MyInterface { 
    Integer myInterfaceMethod(String inputStr); 
    Integer myInterfaceOtherMethod(String inputStr) 
} 

class MyClass implements MyInterface { 
    public Integer myInterfaceMethod(String inputStr) { 
     @Override 
     try { 
      List<String> listDependingOnString = getListByString(inputStr); 
      Integer result = -1; 
      if (inputStr != null) { 
       result = 0; 
       for (String str : listDependingOnString) { 

        // Some different code, given just for example 
        result += str.length(); 

       } 
      } 

      return result; 
     } catch (Exception e) { 
      exceptionProcessing(e); 

      return null; 
     } 
    } 

    @Override 
    public Integer myInterfaceOtherMethod(String inputStr) { 
     try { 
      List<String> listDependingOnString = getListByString(inputStr); 
      Integer result = -1; 
      if (inputStr != null) { 
       result = 0; 
       for (String str : listDependingOnString) { 

        // Some different code, given just for example 
        System.out.println(str); 
        ++result; 

       } 
      } 

      return result; 
     } catch (Exception e) { 
      exceptionProcessing(e); 

      return null; 
     } 
    } 
} 

答えて

2

この特定の例では、ラムダはうまく動作しますが:ここで

private Integer computeStringFunction(String inputStr, BiFunction<Integer,String,Integer> accumulator) { 
    try { 
     List<String> listDependingOnString = getListByString(inputStr); 
     Integer result = -1; 
     if (inputStr != null) { 
      result = 0; 
      for (String str : listDependingOnString) { 
       result = accumulator.apply(result, str); 
      } 
     } 

     return result; 
    } catch (Exception e) { 
     exceptionProcessing(e); 

     return null; 
    } 

public Integer myInterfaceMethod(String inputStr) { 
    return computeStringFunction(inputStr, 
     (Integer oldValue, String str) -> oldValue + str.length()); 
} 

public Integer myInterfaceOtherMethod(String inputStr) { 
    return computeStringFunction(inputStr, 
     (Integer oldValue, String str) -> { 
      System.out.println(str); 
      return oldValue + 1; 
     }); 
} 

「アキュムレータ」は整数、文字列を受け取り、別の整数を返す関数であり、そしてその意図維持することです何らかの種類の「実行中の合計」。

BiFunction documentation

注:はコードでduplicate patternを除去するための鍵は一つの場所に抽象的に共通部分である

2

をテストし、その後にパラメータとして"code pieces"の異なる部分を渡す方法を見つけることができません関数がファーストクラスの市民(JavaScript、Python)である言語に対しては、"code pieces"を関数としてラップすることができます。しかし、Javaのメソッドは値ではないため、Javaのメソッドは値ではないため、解決する方法の1つはinterfaceを定義し、lambda expressionJava 8にはinterfaceを実装するクラスのインスタンスを渡します。 。

common patternは、例として、問題のコードを取る:

  • は、各項目
  • リストやプロセスを繰り返すが、各項目の結果を蓄積し、

を返すその後、我々は定義することができます2つのインターフェース:

@FunctionalInterface 
public interface ItemHandler<T, R> { 
    /** 
    * Takes input item of type T, then returns result of type R 
    */ 
    R handle(T t); 
} 

そしてもう1つの(を表示するために少ない冗長コードを作るために、コードをチェックし、私はすべての例外処理を削除null

@FunctionalInterface 
public interface ItemResultAccumulator<T> { 
    T accumulate(T t1, T t2); 
} 

、その後、あなたのコードは次のようにリファクタリングすることができます:は、結果を蓄積する

public class MyClass implements MyInterface { 
    private static final ItemResultAccumulator<Integer> ADDER = (t1, t2) -> t1 + t2; 

    @Override 
    public Integer myInterfaceMethod(String inputStr) { 
     return processList(getListByString(inputStr), s -> s.length(), ADDER); 
    } 

    @Override 
    public Integer myInterfaceOtherMethod(String inputStr) { 
     return processList(getListByString(inputStr), s -> { 
      System.out.println(s); 
      return Integer.valueOf(1); 
     }, ADDER); 
    } 

    private Integer processList(List<String> list, ItemHandler<String, Integer> handler, ItemResultAccumulator<Integer> accumulator) { 
     Integer result = 0; 
     if (list != null && list.size() > 0) { 
      for (String item : list) { 
       result = accumulator.accumulate(result, handler.handle(item)); 
      } 
     } 

     return result; 
    } 

    private List<String> getListByString(String inputStr) { 
     // Your logic to generate list by input 
     return Lists.newArrayList(inputStr.split(",")); 
    } 
} 

これは私がこの問題を考えていることの少しですが、これが参考になることを願っています:-)

関連する問題