我们的代码有几个处理器,每个处理器都有几个api方法,每个方法都被重载,同样的方法可以接受集合。
例如:
public class Foo {
public X foo(Y y){...}
public Collection<X> foo(Collection<Y> y){... // iterate and execute foo(y) ... }
public Z bar(W w){...}
public Collection<Z> bar(Collection<W> w){... // iterate and execute bar(w) ... }
}
public class Other{
// also method and method on collection
}
当然,关于集合的那些方法实际上是迭代的重复代码 我们正在寻找的是一种制作某种模式或使用泛型的方法,因此迭代集合将实现一次,同样需要一种方式以某种方式传递方法名称。 />
答案 0 :(得分:1)
我建议Startegy pattern。做一些像:
public interface Transformer<X, Y> {
Y transform( X input );
}
class Processor {
public <X,Y> Collection<Y> process( Collection<X> input, Transformer<X, Y> transformer) {
Collection<Y> ret = new LinkedList<Y>();
// generic loop, delegating transformation to specific transformer
for( X x : input) {
ret.add( transformer.transform( x ) );
}
return ret;
}
}
示例:
public static void main( String[] args ) {
List<String> strings = new LinkedList<String>();
strings.add( "1" );
strings.add( "2" );
strings.add( "3" );
Processor p = new Processor();
Collection<Integer> numbers = p.process( strings, new Transformer<String, Integer>() {
@Override
public Integer transform( String input ) {
return Integer.parseInt( input );
}
} );
}
答案 1 :(得分:0)
我无法看到反思在这里有多大帮助。你试图将某些东西替换为微不足道的东西
public Collection<X> foo(Collection<Y> y) {
List<X> result = Lists.newArrayList();
for (Y e : y) result.add(foo(e));
return result;
}
可能会慢得多。我不认为保存这3行(几次)是值得的,但您可能想要尝试注释处理(可能不使用注释)或动态代码生成。在这两种情况下,您都会按原样编写原始类,而不使用集合方法,并使用包含标量和集合方法的不同类。
或者你可能想让它更具功能性:
public class Foo {
public final RichFunction<Y, X> foo = new RichFunction<Y, X>() {
X apply(Y y) {
return foo(y);
}
}
// after some refactoring the original method can be made private
// or inlined into the RichFunction
public X foo(Y y){...}
// instead of calling the original method like
// foo.foo(y)
// you'd use
// foo.foo.apply(y)
// which would work for both the scalar and collection methods
}
public abstract class RichFunction<K, V> extends com.google.common.base.Function<K, V> {
Collection<V> apply(Collection<K> keys) {
List<V> result = Lists.newArrayList();
for (K k : keys) result.add(apply(k));
return result;
}
}
答案 2 :(得分:0)
RUAKH - 我选择实施你的反思建议(虽然,承认,我不喜欢反思)。所以,我做了类似下面的代码谢谢:)
public class Resource {
private static final int CLIENT_CODE_STACK_INDEX;
static {
// Finds out the index of "this code" in the returned stack trace - funny but it differs in JDK 1.5 and 1.6
int i = 0;
for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
i++;
if (ste.getClassName().equals(Resource.class.getName())) {
break;
}
}
CLIENT_CODE_STACK_INDEX = i;
}
public static String getCurrentMethodName() {
return Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX].getMethodName();
}
protected <IN,OUT> Collection<OUT> doMultiple(String methodName, Collection<IN> inCol, Class<?>... parameterTypes){
Collection<OUT> result = new ArrayList<OUT>();
try {
Method m = this.getClass().getDeclaredMethod(methodName, parameterTypes);
if (inCol==null || inCol.size()==0){
return result;
}
for (IN in : inCol){
Object o = m.invoke(this, in);
result.add((OUT) o);
}
}catch (Exception e){
e.printStackTrace();
}
return result;
}
}
public class FirstResource extends Resource{
public String doSomeThing(Integer i){
// LOTS OF LOGIC
return i.toString();
}
public Collection<String> doSomeThing(Collection<Integer> ints){
return doMultiple(getCurrentMethodName(), ints, Integer.class);
}
}
答案 3 :(得分:0)
您应该使用策略模式。通过使用策略模式,您可以省略使用if / else,这会使代码更复杂。策略模式创建的耦合代码更少,更简单。通过使用策略模式,您可以实现更多动态配置代码的方法。所以我建议你使用策略模式。