Builder Pattern (Kurucu Tasarım Kalıbı), karmaşık nesnelerin oluşturulmasını kontrol altına almak ve istemcinin oluşturma süreciyle ilgili detayları bilmeden nesne oluşturmasını sağlamak için kullanılan bir oluşumsal tasarım deseni (creational design pattern)dir. Bu desen, özellikle çok fazla parametre içeren nesnelerin oluşturulmasında kullanılır.
Ne Zaman Kullanılmalıdır?
Builder Pattern şu durumlarda kullanışlıdır:
Karmaşık nesnelerin oluşturulması gerektiğinde: Bir nesne çok fazla bağımsız değişkene sahipse ve farklı kombinasyonlarla oluşturulabiliyorsa.
Kodun daha okunaklı olması gerektiğinde: Çok sayıda parametreli kurucu (constructor) çağırmak yerine adım adım nesne oluşturulmasını sağlar.
Nesne oluşturma sürecinin ayrıştırılması gerektiğinde: Nesnenin nasıl oluşturulduğuna dair mantığı ana koddan ayırarak daha temiz bir kod yapısı sunar.
Builder Pattern'in Avantajları ve Dezavantajları
Avantajlar:
- Esneklik: Nesne oluşturma süreci daha esnek hale gelir.
- Okunaklılık: Kod daha temiz ve anlaşılır olur.
- Karmaşıklığı azaltır: Parametrelerin farklı kombinasyonlarıyla oluşturulabilen nesneler için daha az hata yapma olasılığı sağlar.
- Değişikliklere uyum: Yeni parametreler eklemek daha kolaydır.
Dezavantajlar:
- Ekstra kod gerektirir: Geleneksel constructor kullanımına kıyasla daha fazla sınıf ve kod gerektirir.
- Basit nesneler için gereksiz olabilir: Eğer nesne çok basitse, Builder Pattern kullanmak gereksiz karmaşıklık yaratabilir.
Builder Pattern Kullanım Biçimleri
1. Klasik Builder (Step-by-Step Construction)
class Car {
private String brand;
private String model;
private int year;
private Car(CarBuilder builder) {
this.brand = builder.brand;
this.model = builder.model;
this.year = builder.year;
}
public static class CarBuilder {
private String brand;
private String model;
private int year;
public CarBuilder setBrand(String brand) {
this.brand = brand;
return this;
}
public CarBuilder setModel(String model) {
this.model = model;
return this;
}
public CarBuilder setYear(int year) {
this.year = year;
return this;
}
public Car build() {
return new Car(this);
}
}
@Override
public String toString() {
return "Car [Brand=" + brand + ", Model=" + model + ", Year=" + year + "]";
}
}
// Kullanım
public class Main {
public static void main(String[] args) {
Car car = new Car.CarBuilder()
.setBrand("Toyota")
.setModel("Corolla")
.setYear(2023)
.build();
System.out.println(car);
}
}
2. Fluent Interface Builder
class Computer {
private String CPU;
private int RAM;
private boolean isGraphicsCardEnabled;
private Computer(ComputerBuilder builder) {
this.CPU = builder.CPU;
this.RAM = builder.RAM;
this.isGraphicsCardEnabled = builder.isGraphicsCardEnabled;
}
public static class ComputerBuilder {
private String CPU;
private int RAM;
private boolean isGraphicsCardEnabled;
public ComputerBuilder setCPU(String CPU) {
this.CPU = CPU;
return this;
}
public ComputerBuilder setRAM(int RAM) {
this.RAM = RAM;
return this;
}
public ComputerBuilder setGraphicsCardEnabled(boolean isGraphicsCardEnabled) {
this.isGraphicsCardEnabled = isGraphicsCardEnabled;
return this;
}
public Computer build() {
return new Computer(this);
}
}
@Override
public String toString() {
return "Computer [CPU=" + CPU + ", RAM=" + RAM + "GB, GraphicsCardEnabled=" + isGraphicsCardEnabled + "]";
}
}
// Kullanım
public class Main {
public static void main(String[] args) {
Computer pc = new Computer.ComputerBuilder()
.setCPU("Intel i7")
.setRAM(16)
.setGraphicsCardEnabled(true)
.build();
System.out.println(pc);
}
}
3. Lombok @Builder Kullanımı
Eğer Java’da Lombok kütüphanesi kullanıyorsanız, Builder Pattern’i otomatik olarak oluşturabilirsiniz.
import lombok.Builder;
import lombok.ToString;
@Builder
@ToString
class Phone {
private String brand;
private String model;
private double price;
}
// Kullanım
public class Main {
public static void main(String[] args) {
Phone phone = Phone.builder()
.brand("Apple")
.model("iPhone 14")
.price(999.99)
.build();
System.out.println(phone);
}
}
Gerçek Dünya Senaryosu: Burger Sipariş Sistemi
class Burger {
private String breadType;
private boolean cheese;
private boolean lettuce;
private boolean tomato;
private Burger(BurgerBuilder builder) {
this.breadType = builder.breadType;
this.cheese = builder.cheese;
this.lettuce = builder.lettuce;
this.tomato = builder.tomato;
}
public static class BurgerBuilder {
private String breadType;
private boolean cheese;
private boolean lettuce;
private boolean tomato;
public BurgerBuilder setBreadType(String breadType) {
this.breadType = breadType;
return this;
}
public BurgerBuilder addCheese() {
this.cheese = true;
return this;
}
public BurgerBuilder addLettuce() {
this.lettuce = true;
return this;
}
public BurgerBuilder addTomato() {
this.tomato = true;
return this;
}
public Burger build() {
return new Burger(this);
}
}
}
Sonuç
Builder Design Pattern, karmaşık nesnelerin oluşturulmasını kolaylaştıran güçlü bir tekniktir. Özellikle çok sayıda isteğe bağlı parametre içeren nesneler için oldukça uygundur.