Java'da birçok parametreye sahip kurucuları yönetme


106

Bazı projelerimizde, zincirden aşağı inerken daha fazla parametre ekleyen bir sınıf hiyerarşisi var. En altta, bazı sınıflar 30'a kadar parametreye sahip olabilir ve bunlardan 28'i süper kurucuya aktarılıyor.

Guice gibi bir şey aracılığıyla otomatik DI kullanmanın iyi olacağını kabul edeceğim, ancak bazı teknik nedenlerden dolayı, bu özel projeler Java ile sınırlıdır.

Bağımsız değişkenleri türe göre alfabetik olarak düzenleme kuralı işe yaramaz çünkü bir tür yeniden düzenlenirse (2. bağımsız değişken için geçtiğiniz Çember artık bir Şekildir) aniden sıra dışı olabilir.

Bu soru spesifik olabilir ve "Bu senin sorunun buysa, bunu tasarım düzeyinde yanlış yapıyorsun" eleştirileriyle dolu olabilir, ama ben sadece herhangi bir bakış açısı arıyorum.

Yanıtlar:


266

Oluşturucu Tasarım Kalıbı yardımcı olabilir. Aşağıdaki örneği düşünün

public class StudentBuilder
{
    private String _name;
    private int _age = 14;      // this has a default
    private String _motto = ""; // most students don't have one

    public StudentBuilder() { }

    public Student buildStudent()
    {
        return new Student(_name, _age, _motto);
    }

    public StudentBuilder name(String _name)
    {
        this._name = _name;
        return this;
    }

    public StudentBuilder age(int _age)
    {
        this._age = _age;
        return this;
    }

    public StudentBuilder motto(String _motto)
    {
        this._motto = _motto;
        return this;
    }
}

Bu, aşağıdaki gibi kod yazmamızı sağlar

Student s1 = new StudentBuilder().name("Eli").buildStudent();
Student s2 = new StudentBuilder()
                 .name("Spicoli")
                 .age(16)
                 .motto("Aloha, Mr Hand")
                 .buildStudent();

Gerekli bir alanı (muhtemelen ad gereklidir) bırakırsak, Öğrenci kurucunun bir istisna atmasını sağlayabiliriz. Ve herhangi bir argüman sırasını takip etmemize gerek kalmadan varsayılan / isteğe bağlı argümanlara sahip olmamızı sağlar, çünkü bu çağrıların herhangi bir sırası eşit derecede iyi çalışacaktır.


10
Elbette statik içe aktarımlarda bu "kurucuları" "görmek" zorunda bile değilsiniz. Örneğin, bir oluşturucu döndüren statik yöntem adınız (Dize adı) ve bir öğrenci döndüren Öğrenci (StudentBuilder) olabilir. Dolayısıyla Öğrenci (adı ("Joe"). Age (15) .motto ("Kendimi ıslattım"));
oxbow_lakes

2
@oxbow_lakes: Örneğinizde, hangi sınıfın statik yöntem adı (Dize adı) var?
user443854

Teknik olarak, yeni bir öğrenci oluşturmak için Öğrenci sınıfını kullanmak mümkündür. Yöntemleri Öğrenci sınıfına ekledim ve gayet iyi çalıştı. Bu şekilde başka bir inşaatçı sınıfına ihtiyacım yoktu. Yine de bunun arzu edilir olup olmadığından emin değilim. Oluşturmak için başka bir (StudentBuilder) sınıfı kullanmanın bir nedeni var mı?
WVrock

1
@WVrock: Uygulamanıza bağlı. Cevabımda söylediğim gibi, bunu öğrenci sınıfı ile yapmak, sınıfı yarı başlatılmış bir durumda bırakabilir, örneğin henüz başlatılmamış gerekli bir alanınız varsa.
Eli Courtwright

@EliCourtwright Sanırım tercih / kod tasarımı ile ilgili. Yapıcıyı istisna attırmak yerine, buildStudent()yöntemin istisnayı atmasını sağladım.
WVrock

25

Bir nesnenin içinde ilgili parametreleri kapsülleyebilir misiniz?

örneğin, parametreler şöyle ise


MyClass(String house, String street, String town, String postcode, String country, int foo, double bar) {
  super(String house, String street, String town, String postcode, String country);
  this.foo = foo;
  this.bar = bar;

o zaman bunun yerine sahip olabilirsiniz:


MyClass(Address homeAddress, int foo, double bar) {
  super(homeAddress);
  this.foo = foo;
  this.bar = bar;
}



8

İnşaatçı modelini kullanmak bir çözüm olabilir .

Ama 20-30 parametreye geldiğinizde, parametreler arasında yüksek bir ilişki olduğunu tahmin ediyorum. Dolayısıyla (önerildiği gibi) onları mantıksal olarak aklı başında veri nesnelerine sarmak muhtemelen en mantıklı olanıdır. Bu şekilde veri nesnesi, parametreler arasındaki kısıtlamaların geçerliliğini zaten kontrol edebilir.

Geçmişteki tüm projelerim için, çok fazla parametreye sahip olduğum noktaya geldiğimde (ve bu 28 değil 8 idi!) Daha iyi bir veri modeli oluşturarak kodu sterilize edebildim.


4

Java 1.4 ile sınırlı olduğunuz için, DI istiyorsanız, Spring çok iyi bir seçenek olacaktır. DI, yalnızca yapıcı parametrelerinin hizmetler veya çalışma süresi boyunca değişmeyen bir şey olduğu yerlerde yararlıdır.

Bir nesnenin nasıl oluşturulacağına ilişkin değişken seçenekler istemeniz nedeniyle bu farklı kurucuların tümüne sahipseniz, Oluşturucu modelini kullanmayı ciddi şekilde düşünmelisiniz.


Parametreler, belirttiğiniz gibi çoğunlukla hizmetlerdir ve bu nedenle, ihtiyacım olan şey DI'dır. Sanırım diğer birkaç cevapta bahsedilen İnşaatçı kalıbı tam olarak umduğum şey.
Steve Armstrong

4

En iyi çözüm, kurucuda çok fazla parametrenin olmamasıdır. Yalnızca yapıcıda gerçekten ihtiyaç duyulan parametreler, nesneyi doğru bir şekilde başlatması gereken parametrelerdir. Birden çok parametresi olan kuruculara sahip olabilirsiniz, ancak aynı zamanda yalnızca minimum parametrelere sahip bir kurucuya da sahip olabilirsiniz. Ek kurucular bu basit kurucuyu ve bundan sonra ayarlayıcıları diğer parametreleri ayarlamak için çağırırlar. Bu şekilde, giderek daha fazla parametrelerle zincir probleminden kaçınabilirsiniz, ancak aynı zamanda bazı kolaylık kuruculara da sahip olabilirsiniz.



1

Kalıtım hiyerarşinizin parametrelerinin sayısını ve derinliğini azaltmak için yeniden düzenleme, aklıma gelen tek şey, çünkü hiçbir şey 20-şeylik parametreleri düz tutmaya gerçekten yardımcı olmayacak. Belgelere bakarken her aramayı yapmanız gerekecek.

Yapabileceğiniz bir şey, mantıksal olarak gruplanmış bazı parametreleri kendi üst düzey nesnelerinde gruplamaktır, ancak bunun kendine ait sorunları vardır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.