2016-07-14 3 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); 
} 

이는 모든 유형의 요소 목록을 처리하고 문자열 목록을 반환 할 수 있습니다. 일반적으로 특정 클래스 대신 인터페이스를 반환하는 것이 좋습니다. 특히 클래스에있을 수있는 사용자 정의 메서드를 사용하지 않는 경우에 유용합니다.

public class ProcessorImpl1 implements Processor { 

public ProcessorImpl1(Integer arg1) { 
} 

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

빌더 클래스는 다음과 같이 보일 수 있습니다 :

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); 
} 
} 

내가 년부터 EnumMap는을 사용하는 프로세서 맵을 업데이트 한 다음

는 구현 클래스가 보일 수 있습니다 방법의 예입니다 이러한 종류의 맵은 키가 enum 값이기 때문에 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 패키지를 비공개로 만들거나 정적 초기화 블록으로 만들 수 있습니다. 여기

는 등록 호출 모습입니다 :이 정말`Builder` 패턴을 사용하는 방법을 내가 볼 수없는

registerProcessor(Type.X, ProcessorImpl1.class, new Class[]{Integer.class}, 1); 
    registerProcessor(Type.Y, ProcessorImpl2.class, new Class[]{Integer.class, Integer.class}, 1, 3);