Statik Oluşturma yöntemi - kurucularla karşılaştırıldığında artıları ve eksileri


11

Yapıcılar üzerinde statik nesne oluşturma yöntemlerine sahip olmanın avantajları ve dezavantajları nelerdir?

class Foo {
  private Foo(object arg) { }

  public static Foo Create(object arg) {
    if (!ValidateParam(arg)) { return null; }
    return new Foo(arg);
  }
}

Birkaç düşünebilirim:

Artıları:

  • İstisna atmak yerine null değerini döndürün (adlandırın TryCreate). Bu, istemci tarafında kodu daha kısa ve temiz hale getirebilir. Müşteriler nadiren bir kurucunun başarısız olmasını bekler.
  • Net semantik, örneğin nesnelerin farklı türde oluşturun CreatFromName(String name)veCreateFromCsvLine(String csvLine)
  • Gerekirse önbelleğe alınmış bir nesne veya türetilmiş bir uygulama döndürebilir.

Eksileri:

  • Daha az keşfedilebilir, kod gözden kaçırılması daha zor.
  • Serileştirme veya yansıma gibi bazı desenler daha zordur (ör. Activator<Foo>.CreateInstance())

1
Daha yavaş. Yine de null referans işlemek zorundasınız.
Amir Rezaei

1
@Amir Kullanımı null ( Foo x = Foo.TryCreate(); if (x == null) { ... }). Bir ctor istisnasını işlemek ( Foo x; try { x = new Foo(); } catch (SomeException e) { ... }). Normal bir yöntem çağırırken, hata kodları için istisnaları tercih ederim, ancak nesne oluşturmada TryCreatedaha temiz görünüyor.
dbkk

Doğrulamanızda herhangi bir tür kontrol yapar mısınız?
Amir Rezaei

İkinci Pro ile ilgili olarak, "CreatFromName (String name) ve CreateFromCsvLine (String csvLine) gibi açık semantiğe sahip farklı türde nesneler oluşturma" ile ilgili olarak, yöntem adları aracılığıyla gereksinimleri ifade etmek yerine türler oluşturmak Nameve oluşturmak daha iyi olabilir CsvLine. Bu, Create'i aşırı yüklemenize izin verir. Her ikisi için dize kullanmak "ilkel saplantı" olarak kabul edilebilir (bilinen performans nedenleriyle bu seçimi yapmadığınız varsayılarak). Bunu keşfetmenin eğlenceli bir yolu için Object Calisthenics'e göz atın .
bentayloruk

Yanıtlar:


7

Statik ' içerik oluşturucular ' ile ilgili en büyük dezavantaj muhtemelen kalıtımı sınırlamaktır. Siz veya kitaplığınızın kullanıcısı, sınıfınızdan bir sınıf çıkarırsa Foo, Foo::Create()hemen hemen işe yaramaz hale gelir. Orada tanımlanan tüm mantık devralınan yeniden yazılmalıdır Create().

Bir uzlaşma öneririm: asla başarısız / atmayan önemsiz nesne başlatma mantığına sahip bir kurucu tanımlayın, ardından önbelleğe alma, alternatif inşaat vb. İle yaratıcıları tanımlayın. .


1
Uygulamada bu gerçekten bir sorun değildir, çünkü çoğu sınıf kalıtsal olarak kalılacak şekilde tasarlanmamıştır (ve bu yüzden mühürlenmeli / kesilmelidir). Daha sonra sınıfı mirasa kadar açmak istediğiniz ortaya çıkarsa, her zaman başlatma mantığını korumalı bir kurucuya taşıyabilirsiniz.
Doval

7

Create bir Fabrika yöntemidir. Buna bir ihtiyaç duyduğumda, Fabrika modelini uyguluyorum ve nesneyi ve aynı zamanda gerektiğinde enjekte edilen bir uygulama sınıfını oluşturmak için sözleşmeyi temsil eden bir arabirim tanımlıyorum. Bu, yaratma sorumluluğunu sınıfın dışına taşımanın avantajlarını korur, ancak nesne oluşturucuyu sınıf yapıcısının dışında gerçekleştirme sınırlamalarını önler (veya en azından daha açık hale getirir).

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.