Menu
Coddy logo textTech

Builder Kalıbı

Coddy'nin Java Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 67 / 87.

Builder Deseni, yaygın bir sorunu çözen, nesne oluşturmaya yönelik (creational) bir tasarım desenidir: birçok isteğe bağlı parametreye sahip karmaşık nesnelerin oluşturulması. Birden fazla yapıcı (constructor) oluşturmak veya kullanılmayan parametreler için null geçmek yerine, Builder nesneleri adım adım oluşturmanıza olanak tanır.

Gerekli alanlara (name, email) ve isteğe bağlı alanlara (age, phone, address) sahip bir User nesnesi oluşturmayı düşünün. Bir Builder olmadan, teleskopik yapıcılara veya çok sayıda parametreye sahip karmaşık bir yapıcıya ihtiyaç duyarsınız. Builder deseni daha temiz bir yaklaşım sunar:

public class User {
    private final String name;    // zorunlu
    private final String email;   // zorunlu
    private final int age;        // isteğe bağlı
    private final String phone;   // isteğe bağlı
    
    private User(UserBuilder builder) {
        this.name = builder.name;
        this.email = builder.email;
        this.age = builder.age;
        this.phone = builder.phone;
    }
    
    public static class UserBuilder {
        private final String name;
        private final String email;
        private int age;
        private String phone;
        
        public UserBuilder(String name, String email) {
            this.name = name;
            this.email = email;
        }
        
        public UserBuilder age(int age) {
            this.age = age;
            return this;
        }
        
        public UserBuilder phone(String phone) {
            this.phone = phone;
            return this;
        }
        
        public User build() {
            return new User(this);
        }
    }
}

Builder metotları this döndürerek, nesne oluşturmak için akıcı ve okunabilir bir yol olan metot zincirlemeyi (method chaining) mümkün kılar:

User user = new User.UserBuilder("Alice", "alice@email.com")
    .age(25)
    .phone("555-1234")
    .build();

User kurucusunun private olduğuna dikkat edin; nesneler yalnızca Builder aracılığıyla oluşturulabilir. Bu desen, nesnelerin çok sayıda isteğe bağlı alanı olduğunda parlar ve kodunuzu uzun parametre listelerine kıyasla daha okunabilir ve hataya daha az açık hale getirir.

challenge icon

Görev

Kolay

Builder Pattern kullanarak bir pizza sipariş sistemi oluşturalım! Tüm olası malzemeler ve seçenekler için düzinelerce parametre alan bir yapıcı (constructor) ile uğraşmak yerine, pizza özelleştirmesini temiz ve okunabilir hale getiren akıcı bir builder oluşturacaksınız.

Kodunuzu iki dosya halinde düzenleyeceksiniz:

  • Pizza.java: Oluşturma işlemi için Builder Pattern kullanan bir Pizza sınıfı oluşturun. Pizzanız şu alanlara sahip olmalıdır:

    size (String) - zorunlu, pizza boyutunu temsil eder

    cheese (boolean) - isteğe bağlı, varsayılan olarak false

    pepperoni (boolean) - isteğe bağlı, varsayılan olarak false

    mushrooms (boolean) - isteğe bağlı, varsayılan olarak false

    Pizza yapıcısı private olmalı ve parametre olarak yalnızca bir PizzaBuilder kabul etmeli, builder'daki tüm değerleri pizzanın alanlarına kopyalamalıdır.

    Şu formatta bir dize döndüren bir getDescription() metodu ekleyin: [size] Pizza with: [toppings]; burada toppings, true olan malzemelerin (Cheese, Pepperoni, Mushrooms) virgülle ayrılmış bir listesidir. Hiçbir malzeme seçilmemişse, malzemeler kısmı sadece no toppings demelidir.

    Şunları içeren bir statik iç sınıf (inner class) PizzaBuilder oluşturun:

    • Gerekli size parametresini alan bir yapıcı
    • Her biri ilgili boolean değerini true olarak ayarlayan ve zincirleme kullanım (chaining) için this döndüren cheese(), pepperoni() ve mushrooms() metodları
    • Yeni bir Pizza döndüren bir build() metodu
  • Main.java: Pizza builder'ınızı iş başında gösterin! Dört girdi alacaksınız: pizza boyutu (String) ve sırasıyla peynir, pepperoni ve mantar eklenip eklenmeyeceğini belirten üç adet yes/no değeri (String).

    Verilen boyuta sahip bir PizzaBuilder oluşturun. Ardından, her bir yes/no girdisine göre uygun malzeme metodlarını zincirleyin. Eğer girdi "yes" ise, o malzeme metodunu çağırın; "no" ise atlayın. Son olarak, pizzanızı oluşturmak için build() metodunu çağırın.

    Tamamlanan pizzanız üzerinde getDescription() metodunu çağırmanın sonucunu yazdırın.

Sırasıyla dört girdi alacaksınız: boyut (String), peynir ekle (String: "yes" veya "no"), pepperoni ekle (String: "yes" veya "no"), mantar ekle (String: "yes" veya "no").

Örneğin, Large, yes, no, yes girdileriyle çıktınız şöyle olacaktır: Large Pizza with: Cheese, Mushrooms

Builder Pattern'in, her olasılık için ayrı yapıcılara ihtiyaç duymadan herhangi bir malzeme kombinasyonuyla pizza oluşturmanıza nasıl olanak tanıdığına dikkat edin!

Kopya kağıdı

Builder Deseni, çok sayıda isteğe bağlı parametreye sahip karmaşık nesneleri oluşturmak için kullanılan yaratımsal bir tasarım desenidir. Nesneleri adım adım inşa ederek iç içe geçmiş (telescoping) kuruculardan ve uzun parametre listelerinden kaçınmayı sağlar.

Yapı

Desen şunlardan oluşur:

  • Sadece bir builder kabul eden özel bir kurucuya (private constructor) sahip bir sınıf
  • Nesneyi inşa eden statik bir dahili Builder sınıfı
  • Metot zincirleme (method chaining) için this döndüren Builder metotları
  • Nihai nesneyi oluşturan bir build() metodu

Uygulama Örneği

public class User {
    private final String name;    // zorunlu
    private final String email;   // zorunlu
    private final int age;        // isteğe bağlı
    private final String phone;   // isteğe bağlı
    
    private User(UserBuilder builder) {
        this.name = builder.name;
        this.email = builder.email;
        this.age = builder.age;
        this.phone = builder.phone;
    }
    
    public static class UserBuilder {
        private final String name;
        private final String email;
        private int age;
        private String phone;
        
        public UserBuilder(String name, String email) {
            this.name = name;
            this.email = email;
        }
        
        public UserBuilder age(int age) {
            this.age = age;
            return this;
        }
        
        public UserBuilder phone(String phone) {
            this.phone = phone;
            return this;
        }
        
        public User build() {
            return new User(this);
        }
    }
}

Metot Zincirleme ile Kullanım

User user = new User.UserBuilder("Alice", "alice@email.com")
    .age(25)
    .phone("555-1234")
    .build();

Builder deseni, nesnelerin çok sayıda isteğe bağlı alana sahip olduğu durumlarda idealdir; çok sayıda parametreye sahip kuruculara kıyasla okunabilir ve bakımı kolay kod sağlar.

Kendin dene

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // Girdileri oku
        String size = scanner.nextLine();
        String addCheese = scanner.nextLine();
        String addPepperoni = scanner.nextLine();
        String addMushrooms = scanner.nextLine();
        
        // TODO: Verilen boyuta göre bir PizzaBuilder oluşturun
        // TODO: evet/hayır girdilerine göre malzeme ekleme metotlarını zincirleyin
        // TODO: Pizzayı oluşturun ve açıklamasını yazdırın
        
    }
}
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler