1

我们的代码有几个处理器,每个处理器都有几个 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
}

自然,那些关于集合的方法实际上是迭代的重复代码。
我们正在寻找的是一种创建某种模式或使用泛型的方法,因此对集合的迭代将被实现一次,也为此需要一种以某种方式传递方法名称的方法。

4

4 回答 4

1

我建议Startegy 模式。并执行以下操作:

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 );
            }
        } );
    }
于 2012-10-10T13:35:11.727 回答
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);
    }
}
于 2012-10-10T16:03:39.470 回答
0

您应该使用策略模式。通过使用策略模式,您可以省略使代码更复杂的 if/else 用法。策略模式创建的耦合更少的代码更简单。通过使用策略模式,您可以获得更多动态配置代码的方法。所以我想建议你使用策略模式。

于 2014-06-12T09:01:55.343 回答
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;
    }
}
于 2012-10-10T15:28:39.623 回答