2011-02-01 14 views

उत्तर

11

गोफ पैटर्न निर्माण के चरणों को सारणीबद्ध करने पर केंद्रित है ताकि बिल्डर को बदलकर आप अलग-अलग परिणाम प्राप्त कर सकें जबकि "संशोधित निर्माता" कई रचनाकारों द्वारा अनावश्यक जटिलता की समस्या को लक्षित कर रहा है। तो गोफ पैटर्न अमूर्तता के बारे में अधिक है और संशोधित पटर सादगी (आईएमओ) के बारे में अधिक है।

http://en.wikipedia.org/wiki/Builder_pattern और http://rwhansen.blogspot.com/2007/07/theres-builder-pattern-that-joshua.html में उदाहरणों को देखें और यह स्पष्ट होना चाहिए।

10

नोट Mikko's answer: Hansen's example में कुछ समस्याएं हैं - या, कम से कम, ब्लोच के संस्करण से भिन्नताएं, हालांकि मुझे लगता है कि ब्लोच का संस्करण बेहतर है।

विशेष रूप से:

पहले, Widget के क्षेत्रों Builder.build() में नहीं बल्कि Widget निर्माता की तुलना में स्थापित कर रहे हैं, और इसलिए नहीं कर रहे हैं (और नहीं हो सकता है) finalWidget अपरिवर्तनीय कहा जाता है, लेकिन बाद में सेटर्स जोड़ने और जोड़ने से दूसरे प्रोग्रामर को हतोत्साहित करने के लिए कुछ भी नहीं है।

दूसरा, हैंनसेन की बिल्ड विधि में टिप्पणियां कहती हैं, "पूर्व-निर्माण सत्यापन यहां जाता है"। बलोच (। ईजे 2ed पी .15) का कहना है:

यह महत्वपूर्ण है कि [अपरिवर्तनशीलताओं] ऑब्जेक्ट के लिए बिल्डर से मानकों को कॉपी करने के बाद जाँच की जानी है, और है कि वे बजाय वस्तु क्षेत्रों पर जाँच की जानी बिल्डर फ़ील्ड (आइटम 39)।

[यह] एक और धागे से पैरामीटर में परिवर्तन के खिलाफ वर्ग की रक्षा करता है "असुरक्षा की खिड़की" के बीच के दौरान:

आप आइटम 39 के लिए फ्लिप है (पी। 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

क्या आपका उदाहरण बिगस (या गायब, अस्थिर) गुणों के साथ बिल्डर का कुछ उदाहरण बनाने की अनुमति नहीं देगा और फिर "नया विजेट (myBogusBuilder)" कॉल करें और विजेट के "अस्थिर" उदाहरण के साथ समाप्त हो जाएगा? (उदाहरण के लिए, यह मान्य नहीं है कि कीमत "1" से कम से कम होनी चाहिए, क्योंकि आप केवल उस बिल्ड() विधि में जांच लेंगे) – Rafa

+0

यह होगा कि विजेट कन्स्ट्रक्टर सार्वजनिक था, लेकिन यह निजी है। इसे कॉल करने का एकमात्र तरीका (कक्षा के बाहर से) बिल्ड() के माध्यम से है। –

+1

ओह, सच; ध्यान नहीं दिया (मेरे चश्मे की समीक्षा करने के लिए ...)। धन्यवाद :) – Rafa

संबंधित मुद्दे