3

우리가 공장 방법을 쓸 때 대부분의 경우에, 계속 성장할 수있는 조건은 if입니다. 그러한 방법을 쓰는 가장 효과적인 방법은 무엇입니까 (최소 if 조건)?팩토리 메서드를 작성하는 가장 효과적인 방법은 무엇입니까?

public A createA(final String id) { 
    if (id.equals("A1")) { 
     return new A1(); 
    } 
    else if (id.equals("A2")) { 
     return new A2(); 
    } 
    return null; 
    } 
+1

이 주제는 주관적으로 처리되지 않을 수 있습니다. 이런 종류의 프로그래밍 스타일 질문에 대해서는 http://programmers.stackechange.com이 더 적합했을 것입니다. – oberlies

답변

9

처럼 거의 보이는 Map<String, Supplier<A>> :

Map<String, Supplier<A>> map = new HashMap<>(); 
map.put("A1",() -> new A1()); 
map.put("A2",() -> new A2()); 

... 

public A createA(final String id) { 
    Supplier<A> supplier = map.get(id); 
    if (supplier != null) { 
     return supplier.get(); 
    } 
    throw new IllegalArgumentException("unknown id: " + id); 
} 

이 자바 8 람다 구문, 표준 자바 8 Supplier 인터페이스를 사용하지만, 물론 자신의 공급자를 정의 할 수 있습니다 익명의 내부 클래스를 사용하여 인스턴스를 만들 수 있습니다.

+0

lambda에 익숙하지 않지만,이 게으른 또는 열정적 인 초기화입니까? – Fuhrmanator

+0

@ 칼럼 이것은 기술적으로 열심입니다. 익명 클래스가 즉시 생성되어 _get() _ 메서드를 통해 일부 클래스의 새 인스턴스가 만들어 지지만 필요하지 않을 때까지 지연된 개체가 만들어지지 않습니다. – Marco

1

은 나는 원형의지도 방식을 좋아한다 - 그냥 몇 가지 단계에서 전형을 채우기 - 정적 블록 또는 클래스 생성자에서 중. 코드는 사용할 수있는이

Map<String, A> archetypes; 

    public A createA(final String id) 
    { 
    A a = archetypes.get(id); 
    return (a!=null)?a.copy():null; 
    } 
0

이 방법은 지연 초기화입니다. id의 이름에 해당하는 클래스가 있다고 가정하면

public A createA(final String id) { 
    // warning, should not use an id string that is tainted (eg from user input) 
    return (A) Class.forName(id).newInstance(); 
}