2011-02-01 2 views

답변

11

GoF 패턴은 작성 단계를 추상화하여 "수정 된 빌더"가 여러 생성자가 추가 한 불필요한 복잡성 문제를 해결하는 동안 다른 결과를 얻을 수 있도록합니다. 따라서 GoF 패턴은 추상화에 대한 것이고 수정 된 패턴은 단순성 (IMO)에 관한 것입니다.

http://en.wikipedia.org/wiki/Builder_patternhttp://rwhansen.blogspot.com/2007/07/theres-builder-pattern-that-joshua.html의 예를 살펴보고 명확해야합니다.

10

참고 Mikko's answer : Hansen's example에는 블로흐 버전과의 차이점이 있지만, 블로흐 버전이 우수하다고 생각합니다.

구체적 :

먼저 Widget의 필드 대신 Widget 생성자보다 Builder.build() 설정되어 있으므로되어 있지 (할 수없는) final. Widget은 불변이라고하지만, 나중에 다른 프로그래머가 들어가서 세터를 추가하는 것을 막을 수는 없습니다.

둘째, Hansen의 빌드 방법에 대한 의견은 "사전 생성 유효성 확인은 여기에 있습니다."라고 말합니다. 블로흐 (. EJ 2ed 15 페이지)는 말한다 :

[불변성이] 개체에 빌더에서 매개 변수를 복사 한 후 확인하는 것이 중요하고, 그들이 아닌 개체 필드에서 확인할 수 있음 빌더 필드 (항목 39). "취약점의 창"사이의 기간 동안

는 [이 다른 스레드에서 매개 변수에 대한 변경에 대한 클래스를 보호 : 당신이 항목 39 플립 경우

는 (. P 185) 당신은 이유를 참조 매개 변수를 검사하는 시간 및 매개 변수가 복사되는 시간 Widget에서

필드는 불변하고 방어 복사를 필요로하지 않는,하지만 그럼에도 불구하고 누군가가 나타나서 나중에 Date 배열이나 또는 일부 변경할 수 Collection을 추가하는 경우, 단지 올바른 패턴에 충실 안전합니다 . (또한 build()에 대한 호출의 중간에 Builder을 수정하는 다른 스레드에 대해 보호 할뿐만 아마 최고의 단지 Builder의이 스레드간에 공유되지 확인하기 위해, 그래서 그 안전의 매우 좁은 창입니다.)

더 Blochlike 버전은 다음과 같습니다

public class Widget { 
    public static class Builder { 
     private String name; 
     private String model; 
     private String serialNumber; 
     private double price; 
     private String manufacturer; 

     public Builder(String name, double price) { 
      this.name = name; 
      this.price = price; 
     } 

     public Widget build() { 
      Widget result = new Widget(this); 

      // *Post*-creation validation here 

      return result; 
     } 

     public Builder manufacturer(String value) { 
      this.manufacturer = value; 
      return this; 
     } 

     public Builder serialNumber(String value) { 
      this.serialNumber = value; 
      return this; 
     } 

     public Builder model(String value) { 
      this.model = value; 
      return this; 
     } 
    } 

    private final String name; 
    private final String model; 
    private final String serialNumber; 
    private final double price; 
    private final String manufacturer; 

    /** 
    * Creates an immutable widget instance. 
    */ 
    private Widget(Builder b) { 
     this.name = b.name; 
     this.price = b.price; 
     this.model = b.model; 
     this.serialNumber = b.serialNumber; 
     this.manufacturer = b.manufacturer; 
    } 

    // ... etc. ... 
} 

모든 Widget 필드는 이제 final이며, 모두 건설 후 확인됩니다.

+0

가짜 (또는 누락 된 불안정한) 속성이있는 Builder 인스턴스를 만든 다음 "새 위젯 (myBogusBuilder)"을 호출하고 위젯의 "불안정한"인스턴스로 끝낼 수 없습니까? (예를 들어, build() 메소드에서만 확인했기 때문에 그 가격은 적어도 "1"이상이어야 함을 확인하지 않음). – Rafa

+0

위젯 생성자가 public이지만 사적인 것입니다. 클래스 밖에서 호출하는 유일한 방법은 build()를 사용하는 것입니다. –

+1

오, 참; did not는 그것을 알아 차린다 (나의 안경을 검토 할 것이다. ..). thanks :) – Rafa

관련 문제