2016-04-05 25 views
3

Bu nedenle, ünlü Etkili Java kitabında, bir sınıfı başlatmak için bir iç statik Builder sınıfına sahip olabileceğiniz bir Builder modeli tanıtılmaktadır. Ben anlamakta güçlük çektikleri AncakEtkin Java'da açıklandığı gibi yuvalanmış bir Builder sınıfı gerçekten gerekli mi?

public class Example { 
    private int a; 
    private int b; 

    public static class Builder() { 
     private int a; 
     private int b; 

     public Builder a(int a) { 
      this.a = a; 
      return this; 
     } 

     public Builder b(int b) { 
      this.b = b; 
      return this; 
     } 

     public Example build() { 
      return new Example(this);  
     } 
    } 

    private Example(Builder builder) { 
     this.a = builder.a; 
     this.b = builder.b; 
    } 
} 

neden biz gerçekten bir iç Builder class ihtiyacım var: Kitap bir sınıfın aşağıdaki Tasarım önerir? Yukarıdaki kod, alan bildirimleri için yinelenen satırlara sahiptir (int a, b), daha fazla alanımız olsaydı, bu durum nispeten dağınık olur.

Neden sadece Builder sınıfın kurtulmak ve Example sınıf Builder sınıfında olan tüm set yöntemleri almasına izin alamadım?

Yani Example e = new Example().a(3).b.(3); yerine


Example e = new Example.Builder.a(3).b(3).build(); ait NOT olacaktı, Example örneğini: Kitap parametrelerinin uzun bir liste ayarlanması gereken sınıflar için bu kalıbı önerilir.

+1

Bu, değişmez nesneler üretmek için kullanışlıdır. – shmosel

+0

Bazı karmaşık başlatma durumlarında, değerleriniz zaten ayarlanmış olmalıdır. Ayrıca, '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' Bu durumda – EpicPandaForce

+0

Builder gerekli değildir ve aslında kodu daha ayrıntılı hale getirir. –

cevap

8

Builder, karmaşık nesnelerinin yapımı için bir modeldir. Örneğini karmaşık olarak sayamazdım; aslında, kurucu, sadece yapıcı parametrelerini kullanmaktan çok, gereksiz bir gereksiz kod ekler.

  • karmaşık iletmenin nesneleri oluşturmak için:

    Bir oluşturucu kullanmak isteyeceğinizi birkaç nedeni vardır. Ölçülemeyen nesnelerin nihai (veya mantıksal olarak nihai) alanlara sahip olması gerekir, bu yüzden yapım aşamasında ayarlanmaları gerekir.

    Diyelim ki, N alanınız var, ancak yalnızca belirli kullanım durumlarında bazılarını açıkça belirtmek istiyorsunuz. Parametre listesinin uzunluğu uzadığından ve daha uzun sürdüğü için, “teleskop” olarak bilinen tüm vakaları kapsayacak 2^N kurucuya ihtiyacınız olacaktır. Oluşturucu, isteğe bağlı parametreleri modellemenizi sağlar: Bu parametreyi ayarlamak istemiyorsanız, o setter yöntemini arama. Parametrelerin anlamının belgelenmesine izin vermek için

  • Belirleyici yöntemleri uygun şekilde adlandırarak, değerlerin bir bakışta ne anlama geldiğini görebilirsiniz.

    Aynı zamanda, her bir değerin ne için kullanıldığını görebileceğinizden, aynı türde parametrelerin yanlışlıkla ters çevrilmediğini doğrulamaya da yardımcı olur.

+0

Parametrenin anlamını çıkarmaya izin veren adlandırma yöntemi adlandırma hakkında iyi bir nokta. – KevinO

+0

Teşekkürler Andy, ikinci noktanızın bir kurucu modeli olmadan da elde edilebileceğini söylerken düzelttim mi? (normal ayarlayıcılarla) Yani temelde, yapımcı modeli, yalnızca sınıfımın değişmez olmasını istediğimde işe yarar mı? –

+1

Yani, biri "Oluşturucu benzeri" set yöntemlerini bir sınıfa (ikinci noktanıza ulaşan) belirtebilirdi, ancak bu daha sonra sınıfın değişebilir olmasını sağlar. Bu nedenle, kurucu modeli yararlıdır ** sadece, eğer sınıfımın ikinci noktanızın yararıyla ** değişmez ** olmasını istiyorum. –

1

Dış sınıftaki alanlar sonlanırsa, parametre değerlerini aşamalı olarak belirtmek istiyorsanız, kurucuda tüm alanların başlatılması gerektiğinden, oluşturucu gereklidir. Oluşturucu iç sınıfı, alanların aşamalı olarak başlatılmasına izin verir. Diğerleri de işaret ettiği gibi, bu da değişmez nesneler için de geçerlidir. Alanların nihai olması gerekmez; Dış sınıfa hiçbir setör verilmediyse etkin olacaktır. Yapılandırıcı, parametreleri doğrudan konstrüksiyondan daha verimli bir şekilde biriktirebilir. StringBuilder'u düşünün. Kısmi sonuçları toplamak için geçici bir tampon ayırır. Durumunda "yapı" işlemi toString()'dur.

Son olarak, bir sınıfın yapıcısında yapamayacağınız şeyler olabilir. Bir süper yapıcıya bir değer iletmeniz gerekiyorsa, ancak bu değer yapıcınızın argümanlarının bir parçası değilse, ilk olarak super() numaralı telefonu aramanız ve argüman oluşturmanız mümkün olmayabilir. s) super(...) çağrısında basit bir ifade olarak. BoxLayout akla geliyor. JPanel'u BoxLayout yapıcısına iletirsiniz. Düzeni JPanel yapıcısına iletirsiniz. Tavuk ve yumurta Ve bu kod izin verilmiyor, çünkü this henüz oluşturulmadı. Neyse

class X extends JPanel { 
    X() { 
     super(new BoxLayout(this)); // Error: Cannot use "this" yet 
    } 
} 

bir JPanel değişmez değildir; düzeni inşa ettikten sonra ayarlayabilirsiniz.

+0

Hayır: dış sınıftaki alanlar son ise, bunları açık yapıcı parametreleriyle sağlayabilirsiniz. –

+0

@AndyTurner - Üzgünüm, artımlı yapım için kastettim. Daha net hale getirmek için düzenlerim. – AJNeufeld

+0

@AndyTurner Doğru, ancak kitap, bu kalıbın sadece yapıcı parametresi olarak geçirilemeyen parametrelerin loooong listesi olan nesneler için yararlı olduğunu öne sürmektedir. Karışıklık için özür dilerim, –

1

Gerekçe karmaşık sınıflar içindir.

Example exp = Example.Builder().a(5).b(10).build(); 

Apaçi çeşitli değerlerin artan ayarını sağlamak için bazı durumlarda bu yaklaşımı kullanır: biri gibi, zincirleme yapabilirsiniz böylece Builder nesne, kendisini döndüren dikkat edin. Ayrıca, .build() yönteminin, istenirse bir nesne oluşturmak için tüm doğru değerlerin bir miktar kontrolünü yapmasına izin verir.

+0

Teşekkür ederim Kevin, bu anlayışlı, +1! –

İlgili konular