寻找合适的设计模式

时间:2012-10-10 13:13:05

标签: java oop design-patterns

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

答案 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,这会使代码更复杂。策略模式创建的耦合代码更少,更简单。通过使用策略模式,您可以实现更多动态配置代码的方法。所以我建议你使用策略模式。