有时候,方法在他们身体的中间位置有唯一的区别,很难将它们概括为一般,或者将代码的常用部分提取到单个方法中。
问题本身:您如何重构以下接口方法的实现,以避免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;
}
}
}
答案 0 :(得分:2)
对于这个特殊的例子,lambda可以很好地工作:
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;
});
}
&#34;累加器&#34;这是一个函数,它接受一个整数和一个字符串,并返回另一个整数,其目的是保持&#34;运行总数&#34;某种。
注意:未经过测试
答案 1 :(得分:2)
在代码中删除duplicate pattern
的关键是将公共部分抽象到一个地方然后找到一种方法来传递"code pieces"
的不同部分作为执行的参数,对于其中函数是一等公民(JavaScript,Python),你总是可以将"code pieces"
包装为函数。但它不适用于Java,因为Java中的方法不是值,解决它的一种方法是定义interface
,然后传递实现interface
的类的实例。作为参数,lambda expression
中的Java 8
可以更简单。
以相关代码为例,common pattern
为:
然后我们可以定义两个接口:
@FunctionalInterface
public interface ItemHandler<T, R> {
/**
* Takes input item of type T, then returns result of type R
*/
R handle(T t);
}
另一个interface
来积累结果:
@FunctionalInterface
public interface ItemResultAccumulator<T> {
T accumulate(T t1, T t2);
}
然后您的代码可以重构为(我删除了所有异常处理和null
检查代码,以使代码更简洁,无法查看):
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(","));
}
}
这是我对这个问题的一点思考,希望这可能会有所帮助: - )