2016-07-14 15 views
2

は、私がこのようなコードを持っている:私はインターフェイスを持って工場とビルダーのパターンの組み合わせですか?

public class ProcessorBuilder { 
    enum Type { 
     X, 
     Y, 
    } 

    private static HashMap<Type, Processor> processors = new HashMap<>(); 
    public static void buildProcessors(int arg1, String arg2, CustomObject arg3) { 
     processors.put(Type.X, new ProcessorImpl1(arg1, arg2)); 
     processors.put(Type.Y, new ProcessorImpl2(arg3));  
    } 

public Processor getProcessor(Type type) { 
    return processors.get(type); 
} 

public interface Processor { 
    public ArrayList<String> process(ArrayList<CustomObject> input); 
} 

は、コードがそのクリーンではないようです。私は工場とビルダーのパターンの組み合わせの何かを必要と感じる。
私がここで間違って何をやっているか、どのように私はこれを改善することができますか?

+1

。確かに 'Processor' ..しかし、私はあなたが好きなら、' Processor'と 'ProcessorRegistry'または' ProcessorFactory'のようなものを使用するように誘惑されるだろう。 – vikingsteve

答えて

1

あなたはこのような何かにプロセッサ・インターフェースをリファクタリングすることができます。これは、それは要素の任意のタイプのリストを処理し、文字列のリストを返すことができるようになります

public interface Processor { 
    List<String> process(List<?> input); 
} 

。通常は、特定のクラスの代わりにインターフェイスを返すことをお勧めします。特に、クラスが持つカスタムメソッドを使用しない場合は、このメソッドを使用することをお勧めします。私は以来、EnumMapを使用するプロセッサ・マップを更新しました

public class ProcessorBuilder { 
enum Type { 
    X, 
    Y, 
} 

private static final Map<Type, Processor> processors = new EnumMap<>(Type.class); 

public static <T extends Processor> void registerProcessor(Type type, Class<? extends T> processorClass, 
                   Class[] paramsClass, Object... params) 
     throws IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException { 

     final Constructor<? extends T> constructor = processorClass.getConstructor(paramsClass); 
     final Processor processor = constructor.newInstance(params); 
     processors.put(type, processor); 
} 

public static Processor getProcessor(Type type) { 
    return processors.get(type); 
} 

public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException { 
    registerProcessor(Type.X, ProcessorImpl1.class, new Class[]{Integer.class}, 1); 
    registerProcessor(Type.Y, ProcessorImpl2.class, new Class[]{Integer.class, Integer.class}, 1, 3); 
    Processor p1 = getProcessor(Type.X); 
    p1.process(null); 
    Processor p2 = getProcessor(Type.Y); 
    p2.process(null); 
} 
} 

public class ProcessorImpl1 implements Processor { 

public ProcessorImpl1(Integer arg1) { 
} 

@Override 
public List<String> process(List<?> input) { 
    return Collections.emptyList(); 
} 
} 

をビルダークラスは次のようになります。ここでは

は、実装クラスが見えるかもしれ方法の一例ですキーは列挙型の値なので、この種のマップはHashMapより優れたパフォーマンスを持ちます。あなたは(EnumMapで)キーまたは(EnumSetの中)の値として列挙型を使用する場合は、常にEnumMapまたはEnumSetのを使用する必要があります。

registerProcessor

方法は、リフレクションを使用してプロセッサインタフェースを実装するクラスの新しいインスタンスを構築するために使用されます。

final Constructor<? extends T> constructor = processorClass.getConstructor(paramsClass); 

processorClassパラメータは、作成するオブジェクトのクラスを示します。私たちは、paramsClass配列の要素と同じパラメータタイプ(および順序)を持つクラスのコンストラクタを取得するためにそれを使用(箱入りプリミティブはprimitesの代わりに使用します。

final Processor processor = constructor.newInstance(params); 

我々は必要なの新しいインスタンスを作成しますパラメータの数と型は、上記のコンストラクタで期待されるものと同じでなければなりません。そうでなければ、 newInstance呼び出しは失敗します。

これで、新しく作成されたパラメータをマップに置きます。あなたがしたい内容に応じて、それを同期させるために必要な場合があり

registerProcessorおよびgetProcessorメソッド。コードからのみプロセッサを登録することが分かっている場合は、registerParametersパッケージをプライベートにするか、静的なinitブロックにすることができます。ここで

は、登録呼び出しがどのように見えるかです:これは本当に `Builder`パターンを使用してどのように私は見ていない

registerProcessor(Type.X, ProcessorImpl1.class, new Class[]{Integer.class}, 1); 
    registerProcessor(Type.Y, ProcessorImpl2.class, new Class[]{Integer.class, Integer.class}, 1, 3); 
関連する問題