![translation](https://cdn.durumis.com/common/trans.png)
Bu, AI tarafından çevrilen bir gönderidir.
Dil Seç
Text summarized by durumis AI
- Çok sayıda parametreli oluşturucuları verimli bir şekilde yönetmek için çeşitli desenleri tanıtır ve kademeli oluşturucu deseninin, Java Bean'lerin deseninin ve oluşturucu deseninin avantajlarını ve dezavantajlarını karşılaştırır ve analiz eder.
- Oluşturucu deseni, kodun okunabilirliğini ve kararlılığını artırmanın avantajına sahiptir ve özellikle hiyerarşik olarak tasarlanmış sınıflarla kullanıldığında daha da etkilidir.
- Oluşturucu deseni kodu daha açık bir şekilde yazmaya olanak tanır, ancak oluşturucu nesnesi oluşturma ve kodun uzunluğu gibi dezavantajları da vardır.
Yükselen Oluşturucu Desen
Statik fabrika ve oluşturucular, çok sayıda parametreyle başa çıkmakta zorlanırlar. Örneğin, bir sınıfın 6 alanı varsa ve 2 parametreyle, 3 parametreyle, ... bir oluşturucu oluşturmak isterseniz, aşağıdaki gibi yükselen oluşturucu desenini kullanabilirsiniz.
public class NutritionFacts {
private final int servingSize;
private final int servings;
private final int calories;
private final int fat;
private final int sodium;
private final int carbohydrate;
public NutritionFacts(int servingSize, int servings, int calories, int fat, int sodium, int carbohydrate) {
this.servingSize = servingSize;
this.servings = servings;
this.calories = calories;
this.fat = fat;
this.sodium = sodium;
this.carbohydrate = carbohydrate;
}
public NutritionFacts(int servingSize, int servings) {
this(servingSize, servings, 0, 0, 0, 0);
}
public NutritionFacts(int servingSize, int servings, int calories) {
this(servingSize, servings, calories, 0, 0, 0);
}
public NutritionFacts(int servingSize, int servings, int calories, int fat) {
this(servingSize, servings, calories, fat, 0, 0);
}
public NutritionFacts(int servingSize, int servings, int calories, int fat, int sodium) {
this(servingSize, servings, calories, fat, sodium, 0);
}
Ancak bu bile, parametre sayısı artarsa, kodu okurken her değerin ne anlama geldiği karışır ve aynı türdeki parametreler karıştırılıp yanlış değerler girilebilir.
Java Bean'ler Deseni
Java Bean'ler deseni, parametresiz bir oluşturucuyla nesne oluşturup, setter metotlarını çağırarak istediğiniz parametre değerlerini ayarlama şeklidir.
public class NutritionFactsWithJavaBeansPattern {
private int servingSize = -1; // Zorunlu. Varsayılan değer yok.
private int servings = -1; // Zorunlu. Varsayılan değer yok.
private int calories;
private int fat;
private int sodium;
private int carbohydrate;
public void setServingSize(int servingSize) {
this.servingSize = servingSize;
}
public void setServings(int servings) {
this.servings = servings;
}
public void setCalories(int calories) {
this.calories = calories;
}
public void setFat(int fat) {
this.fat = fat;
}
public void setSodium(int sodium) {
this.sodium = sodium;
}
public void setCarbohydrate(int carbohydrate) {
this.carbohydrate = carbohydrate;
}
Java Bean'ler deseni, parametre sayısı artsa bile, değerleri karıştırmadan bir örnek oluşturabilir. Ancak, bir nesne oluşturmak için birkaç setter metodu çağırmak gerekir ve nesne tamamen tamamlanana kadar tutarlılık bozulur. Bu nedenle sınıfı değişmez hale getiremiyorsunuz.
Oluşturucu Deseni
Yükselen oluşturucu deseninin güvenilirliğini ve Java Bean'ler deseninin okunabilirliğini birleştiren oluşturucu deseni çoğunlukla kullanılır.
İstemci, ihtiyaç duyulan nesneyi doğrudan oluşturmak yerine, yalnızca zorunlu parametrelerle oluşturucuyu çağırıp bir oluşturucu nesnesi alır. Daha sonra, oluşturucu nesnesinin sağladığı bir tür setter metotlarıyla istediğiniz isteğe bağlı parametreleri ayarlar. Son olarak, parametresiz build() metodunu çağırıp gerekli nesneyi alır.
public class NutritionFactsWithBuilderPattern {
private final int servingSize;
private final int servings;
private final int calories;
private final int fat;
private final int sodium;
private final int carbohydrate;
private NutritionFactsWithBuilderPattern(Builder builder) {
servingSize = builder.servingSize;
servings = builder.servings;
calories = builder.calories;
fat = builder.fat;
sodium = builder.sodium;
carbohydrate = builder.carbohydrate;
}
public static class Builder {
private final int servingSize;
private final int servings;
private int calories;
private int fat;
private int sodium;
private int carbohydrate;
public Builder(int servingSize, int servings) {
this.servingSize = servingSize;
this.servings = servings;
}
public Builder calories(int val) {
calories = val;
return this;
}
public Builder fat(int val) {
fat = val;
return this;
}
public Builder sodium(int val) {
sodium = val;
return this;
}
public Builder carbohydrate(int val) {
calories = val;
return this;
}
public NutritionFactsWithBuilderPattern build() {
return new NutritionFactsWithBuilderPattern(this);
}
}
Builder sınıfındaki oluşturucu, yalnızca zorunlu parametreleri alır ve diğer isteğe bağlı parametreler bir tür setter metoduyla doldurulur. Ve son olarak build() metodu aracılığıyla tamamlanmış NutritionFactsWithBuilderPattern nesnesi oluşturulur. NutritionFactsWithBuilderPattern sınıfı değişmezdir ve oluşturucunun setter metotları oluşturucuyu kendisini döndürdüğü için ardışık olarak çağrılabilir. Bu şekildeki bir yöntem, akıcı API veya metot zincirleme olarak adlandırılır.
NutritionFactsWithBuilderPattern nutritionFacts =
new NutritionFactsWithBuilderPattern.Builder(240, 8)
.calories(100)
.sodium(35)
İstemci açısından bakıldığında, oluşturucu deseniyle kod yazmak ve okumak kolaydır.
Hiyerarşik Olarak Tasarlanmış Sınıflarla İyi Uyum Sağlayan Oluşturucu Deseni
public abstract class Pizza {
public enum Topping {
HAM, MUSHROOM, ONION, PEPPER, SAUSAGE
}
final Set toppings;
Pizza(Builder> builder) {
toppings = builder.toppings.clone();
}
abstract static class Builder> {
private EnumSet toppings = EnumSet.noneOf(Topping.class);
public T addTopping(Topping topping) {
toppings.add(topping);
return self();
}
abstract Pizza build();
protected abstract T self();
}
Pizza.Builder sınıfı, özyinelemeli tür sınırlaması kullanan bir jenerik tür olup, self() adlı bir soyut metot eklenerek alt sınıflarda dönüştürme yapmadan metot zincirlemesini destekler. Alt sınıflarda bu soyut metodun dönüş değerini kendilerine atamaları yeterlidir.
Şimdi, Pizza'nın alt sınıfları olan New York pizzası ve Calzone pizzasına bakarak, oluşturucu deseninin esnekliğini deneyelim.
public class NyPizza extends Pizza {
public enum Size {
SMALL, MEDIUM, LARGE
}
private final Size size; // Zorunlu parametre
private NyPizza(Builder builder) {
super(builder);
size = builder.size;
}
public static class Builder extends Pizza.Builder {
private final Size size;
public Builder(Size size) {
this.size = size;
}
@Override
NyPizza build() {
return new NyPizza(this);
}
@Override
protected Builder self() {
return this;
}
}
}
public class CalzonePizza extends Pizza {
private final boolean sauceInside; // İsteğe bağlı parametre
private CalzonePizza(Builder builder) {
super(builder);
sauceInside = builder.sauceInside;
}
public static class Builder extends Pizza.Builder {
private boolean sauceInside = false;
public Builder sauceInside() {
sauceInside = true;
return this;
}
@Override
CalzonePizza build() {
return new CalzonePizza(this);
}
@Override
protected Builder self() {
return this;
}
}
Her alt sınıfın oluşturucusunda tanımlanan build() sınıfı, somut alt sınıfı döndürüyor. Alt sınıfın metotlarının, üst sınıfın metodlarının döndürdüğü tür değil, o alt türü döndürme özelliğine kovaryant dönüş türlendirme denir. Bu özelliği kullanarak istemci dönüştürme yapmak zorunda kalmaz.
NyPizza nyPizza = new NyPizza.Builder(Size.SMALL)
.addTopping(Topping.SAUSAGE)
.addTopping(Topping.ONION)
.build();
CalzonePizza calzonePizza = new CalzonePizza.Builder()
.addTopping(Topping.HAM)
.sauceInside()
İstemci açısından bakıldığında, Pizza'nın numaralandırması ve her alt sınıfın numaralandırması birleştirilebilir ve her birine uygun metotlarla nesne tamamlanabilir.
Oluşturucu Deseninin Dezavantajları
- Bir oluşturucu nesnesi oluşturmanız gerekir.
- Kod uzun olur.
Özet
Oluşturucu veya statik fabrika metodunda işlenmesi gereken çok sayıda parametre varsa, oluşturucu desenini göz önünde bulundurun.
Kaynak
- Etkili Java