Logo
Ana Sayfa
ÖZEL KODLAMA DERSLERİ
Yazılım Özel Ders
Tüm birebir programlara genel bakış
Python Yazılım Kursu
Sıfırdan ileri seviyeye birebir Python
Java Yazılım Kursu
OOP odaklı birebir Java eğitimi
AP Computer Science Principles
AP CSP sınav hazırlığı
GRUP DERSLERİ
Python & Django Masterclass
SINIRLI KONTENJAN
Java & Spring Boot Masterclass
SINIRLI KONTENJAN
C# .NET Masterclass
SINIRLI KONTENJAN
VİDEO DERSLER
Sıfırdan Temel Python Kursu
Kendi Hızında Öğren
ÜCRETSİZ
Seviye Testi
Ücretsiz — Python, Java, algoritma seviye testleri
Kariyerini Keşfet
Sertifika Doğrula
Belge numarası ve soyad ile doğrulama

Java'da Builder Deseni: Çok Parametreli Constructor Sorununa Çözüm

Yazar: Berk Keskin 28.08.2026 ~13 dk okuma 4 Okunma
java-builder-deseni-nesne-olusturma

Bir Java sınıfındaki alan sayısı arttıkça, o sınıfı örneklemek için kullanılan constructor çağrıları da giderek anlaşılmaz ve hataya açık hale gelir; çünkü art arda sıralanmış beş altı parametrenin her birinin ne anlama geldiğini çağrı satırından anlamak mümkün olmaz. Java'da builder deseni tam olarak bu noktada devreye girer: nesneyi tek bir uzun constructor çağrısıyla değil, adım adım ve isimli metotlarla inşa etmeyi mümkün kılar. Bu yazıda önce sorunun kaynağına, ardından çözümün kod üzerindeki karşılığına bakacağız.

Çok Parametreli Constructor'lar Neden Okunabilirlik Sorunu Yaratır?

Bir sınıfın alan sayısı ikiyi üçü geçtiğinde, o sınıftan nesne üretmek için yazılan constructor çağrısı okunması zor bir parametre dizisine dönüşür. Sorun, dilin kendisinden değil, tek bir constructor'ın çok fazla sorumluluk taşımaya zorlanmasından kaynaklanır. Geliştirici, sınıfı farklı senaryolarda kullanabilmek için genellikle aynı sınıfa parametre sayısına göre üst üste yüklenmiş birden çok constructor ekler; bu yaklaşıma telescoping constructor denir ve her yeni opsiyonel alan geldiğinde bir yeni constructor daha eklenerek sınıf giderek şişer.

Telescoping constructor yaklaşımının asıl bedeli, çağrı anında ödenir. Bir metoda beş ya da altı pozisyonel argüman geçtiğinizde, hangi değerin hangi alanı temsil ettiğini anlamak için sınıfın tanımına geri dönüp bakmanız gerekir. Kod editörü size parametre isimlerini ipucu olarak gösterse de, gerçek bir üretim ortamında kod inceleme yaparken veya aylar sonra kendi yazdığınız kodu tekrar okurken bu ipucu her zaman elinizin altında olmaz. Sonuç olarak, tamamen geçerli görünen bir satır, aslında birbirine yakın türden iki değerin yerinin karışmış olduğu sessiz bir hatayı içerebilir.

Bu durum özellikle aynı türden birden fazla parametre olduğunda ciddileşir. İki farklı int alanı veya iki farklı String alanı yan yana sıralandığında, derleyici için bu parametreler tamamen geçerlidir; çünkü tip uyumu sağlanmıştır. Ancak anlam düzeyinde bir karışıklık söz konusudur ve bu karışıklığı derleyici değil, yalnızca dikkatli bir insan gözü veya çalışma zamanında ortaya çıkan yanlış sonuç fark edebilir. İşte bu noktada, nesne oluşturma sürecinin kendisini yeniden tasarlamak gerekir; bir sonraki bölümde bu sorunu somut bir Java sınıfı üzerinden göreceğiz.

Telescoping Constructor Örneği: Kod Üzerinden Sorunu Görmek

Sorunu soyut biçimde anlatmak yerine, gerçek bir sınıf üzerinden göstermek daha ikna edicidir. Aşağıda bir Bilgisayar sınıfı var: işlemci, RAM miktarı, depolama miktarı, ekran kartı modeli ve garanti süresi gibi alanları içeriyor. Sınıf, farklı kullanım senaryolarını desteklemek için üst üste yüklenmiş constructor'lar barındırıyor; bu tam olarak telescoping constructor yaklaşımının klasik hâli.

public class Bilgisayar {
    private String islemci;
    private int ramGB;
    private int depolamaGB;
    private String ekranKartiModeli;
    private int garantiSuresiAy;

    public Bilgisayar(String islemci, int ramGB) {
        this(islemci, ramGB, 256, "Entegre Ekran Karti", 12);
    }

    public Bilgisayar(String islemci, int ramGB, int depolamaGB) {
        this(islemci, ramGB, depolamaGB, "Entegre Ekran Karti", 12);
    }

    public Bilgisayar(String islemci, int ramGB, int depolamaGB,
                       String ekranKartiModeli, int garantiSuresiAy) {
        this.islemci = islemci;
        this.ramGB = ramGB;
        this.depolamaGB = depolamaGB;
        this.ekranKartiModeli = ekranKartiModeli;
        this.garantiSuresiAy = garantiSuresiAy;
    }
}

Şimdi bu sınıftan bir nesne oluşturalım. Geliştirici 16 GB RAM ve 512 GB depolamalı bir bilgisayar tanımlamak istiyor, ama parametreleri yanlış sırayla yazıyor:

Bilgisayar yanlisBilgisayar =
    new Bilgisayar("Intel i7", 512, 16, "RTX 4060", 24);
// Amaç: 16 GB RAM, 512 GB depolama
// Gerçekte üretilen: 512 GB RAM, 16 GB depolama

Bu satır derleyici açısından tamamen geçerlidir; çünkü ramGB ve depolamaGB parametreleri ikisi de int türündedir ve derleyici bir int değerin başka bir int yerine geçmesini engelleyemez. Hata, ancak nesne kullanıma alındığında, örneğin ekrana yazdırıldığında veya bir iş kuralında kontrol edildiğinde fark edilir. Yani bu tür bir mantık hatası derleme zamanında değil, çalışma zamanında ve genellikle en uygun olmayan anda ortaya çıkar. Alan sayısı arttıkça bu risk de doğrusal olarak büyür ve sınıfı kullanan her yeni geliştirici için tuzak sayısı çoğalır.

Builder Tasarım Deseni Nedir? Temel Mantığı

Builder Tasarım Deseni Nedir? Temel Mantığı

Builder deseni, bir nesneyi tek bir uzun constructor çağrısıyla değil, adım adım ve her adımı isimlendirerek inşa etme fikrine dayanır. Amaç, çağrı satırındaki her değerin ne anlama geldiğini pozisyonundan değil, çağrıldığı metodun isminden anlaşılır kılmaktır. Bunu sağlamak için sınıfın kendisine değil, o sınıfı inşa etmekle görevli ayrı bir Builder sınıfına ihtiyaç vardır; bu sınıf genellikle asıl sınıfın içine statik iç sınıf olarak tanımlanır ve yalnızca nesne oluşturma sürecinden sorumludur.

Builder yapısının mantığı, alanları zorunlu ve opsiyonel olarak ayırmaktan geçer. Zorunlu alanlar Builder'ın kendi constructor'ında istenir, çünkü bunlar olmadan nesnenin anlamlı bir hâli yoktur; işlemci ve RAM gibi alanlar buna örnek olabilir. Opsiyonel alanlar ise isimli metotlarla, örneğin ekranKarti("RTX 4060") veya garanti(24) gibi çağrılarla tek tek eklenir. Bu ayrım, bir önceki bölümde gördüğümüz gibi tüm alanları aynı constructor'a doldurma zorunluluğunu ortadan kaldırır.

Bu mantığı OOP temelli bir eğitim sürecinde ilk kez gören bir öğrenci için en kritik nokta, Builder'ın kendisinin de bir sınıf olduğunu kavramaktır; yani nesne oluşturma sorumluluğu, oluşturulan nesnenin kendisinden ayrılmış olur. Bu ayrım ilk bakışta fazladan kod yazmak gibi görünse de, aslında her metodun tek bir işten sorumlu olması ilkesinin doğal bir sonucudur. Bu tür temel tasarım mantığını kod yazarak, gerçek örnekler üzerinde deneyerek içselleştirmek isteyen öğrenciler için canlı yazılım eğitimi programları bu geçişi adım adım, birebir uygulamalı örneklerle destekleyen bir ortam sunar. Bir sonraki bölümde Builder'ın çağrı zincirini mümkün kılan method chaining mekanizmasına ve tam kod örneğine geçiyoruz.

Method Chaining: this Döndüren Metotlarla Akıcı Kod Yazma

Method chaining, Builder deseninin okunabilirliği artıran asıl mekanizmasıdır. Mantığı basittir: Builder sınıfındaki her ayarlama metodu (örneğin ram(), ekranKarti()) parametreyi alıp ilgili alanı doldurduktan sonra void döndürmez; kendi nesnesini, yani this'i geri döndürür. Bir metot çağrısı kendi üzerinde çalıştığı nesneyi döndürdüğü için, o dönüş değerinin üzerinden hemen bir başka metot çağrılabilir. Bu zincir, noktalarla birbirine eklenmiş bir cümle gibi okunur ve kodu adım adım anlatan bir akışa dönüştürür.

Önceki bölümdeki telescoping constructor çağrısını hatırlayalım: new Bilgisayar("Intel i7", 16, 512, "RTX 3060", true, false). Aynı nesneyi Builder ile oluşturduğumuzda kod şu hâle gelir:

public class Bilgisayar {
    private final String islemci;
    private final int ram;
    private final int depolama;
    private final String ekranKarti;
    private final boolean wifiVarMi;

    private Bilgisayar(Builder builder) {
        this.islemci = builder.islemci;
        this.ram = builder.ram;
        this.depolama = builder.depolama;
        this.ekranKarti = builder.ekranKarti;
        this.wifiVarMi = builder.wifiVarMi;
    }

    public static class Builder {
        private String islemci;
        private int ram;
        private int depolama;
        private String ekranKarti;
        private boolean wifiVarMi;

        public Builder islemci(String islemci) {
            this.islemci = islemci;
            return this;
        }

        public Builder ram(int ram) {
            this.ram = ram;
            return this;
        }

        public Builder depolama(int depolama) {
            this.depolama = depolama;
            return this;
        }

        public Builder ekranKarti(String ekranKarti) {
            this.ekranKarti = ekranKarti;
            return this;
        }

        public Builder wifiVar(boolean wifiVarMi) {
            this.wifiVarMi = wifiVarMi;
            return this;
        }

        public Bilgisayar build() {
            return new Bilgisayar(this);
        }
    }
}

// Kullanım:
Bilgisayar bilgisayar = new Bilgisayar.Builder()
        .islemci("Intel i7")
        .ram(16)
        .depolama(512)
        .ekranKarti("RTX 3060")
        .wifiVar(true)
        .build();

İki örneği yan yana koyduğumuzda fark açıkça görülür: telescoping constructor çağrısında altı değer art arda sıralanmış hâlde durur ve hangi değerin hangi alana ait olduğunu anlamak için sınıfın tanımına bakmak gerekir. Builder çağrısında ise her satır kendi anlamını taşır; .ram(16) okunduğunda bunun RAM değeri olduğu, .ekranKarti("RTX 3060") okunduğunda bunun ekran kartı olduğu tek bakışta anlaşılır. Zincirleme çağrı, kodu yazan kişi için de okuyan kişi için de bir tür otomatik dokümantasyon görevi görür; parametre sırasını ezberlemeye gerek kalmaz, sadece hangi metodun hangi alanı ayarladığını bilmek yeterlidir. Ayrıca yeni bir alan eklendiğinde mevcut çağrılar bozulmaz, sadece isteğe bağlı yeni bir .metot() satırı eklenir.

Builder ile Telescoping Constructor Karşılaştırması

Builder ile Telescoping Constructor Karşılaştırması

İki yaklaşımı aynı kriterler üzerinden yan yana koyduğumuzda, hangi durumda hangisinin daha sağlıklı bir tercih olduğu netleşir. Aşağıdaki tablo, önceki bölümlerde incelediğimiz Bilgisayar örneğinden bağımsız olarak, iki yaklaşımın kavramsal düzeyde nasıl farklılaştığını özetler.

Kriter Telescoping Constructor Builder Deseni
Okunabilirlik Parametre sırası ezberlenmeli, değerlerin anlamı çağrı noktasında görünmez Her değer kendi metot adıyla birlikte okunur, anlam çağrı satırında görünür
Hata Riski Aynı tipteki parametrelerin sırası kolayca karışabilir Alan adı metot adına bağlı olduğu için yanlış alana değer atama riski azalır
Esneklik Her parametre kombinasyonu için ayrı bir overload gerekir İstenilen alanlar istenilen sırayla, gerekenler dışındakiler atlanarak ayarlanabilir
Kod Miktarı Az sayıda alanda kısa, çok alanda hızla şişer Başlangıçta ek bir Builder sınıfı gerektirir, alan sayısı arttıkça oransal olarak daha az şişer

Tablodan çıkan sonuç şudur: telescoping constructor'ın tek avantajı azlıktır ve bu avantaj alan sayısı arttıkça hızla kaybolur. Builder deseni ise başlangıçta biraz daha fazla kod gerektirse de, bu maliyeti okunabilirlik ve hata güvenliği ile karşılar. Bir sonraki bölümde bu maliyetin her durumda mantıklı olup olmadığına, yani Builder'ın gerçekten ne zaman tercih edilmesi gerektiğine bakacağız.

Builder Deseni Ne Zaman Gerçekten Gerekli?

Builder deseni her sınıf için doğru çözüm değildir ve bunu net söylemek gerekir. Bir sınıfın sadece iki veya üç alanı varsa ve bu alanların büyük kısmı zorunluysa, ayrı bir Builder sınıfı yazmak gereksiz bir kod hacmi (overhead) yaratır. Örneğin sadece ad ve yas alanı olan bir Kisi sınıfı için Builder yazmak, tek bir constructor'ın çözeceği işi birden fazla sınıfa ve metoda yaymak anlamına gelir; bu da kodu basitleştirmek yerine karmaşıklaştırır.

Builder'ın gerçekten fayda sağladığı yer, bir sınıfın çok sayıda alanı olduğu ve bu alanların önemli bir kısmının opsiyonel olduğu durumlardır. Bilgisayar örneğinde işlemci ve RAM zorunlu olabilirken, Wi-Fi desteği, Bluetooth desteği veya ek soğutma sistemi gibi alanlar isteğe bağlıdır ve her nesne için farklı kombinasyonlarla ayarlanabilir olmalıdır. Aynı durum, bir API isteği gönderen HTTP istemcisi, farklı görsel ayarlarla oluşturulan bir arayüz bileşeni veya çok sayıda yapılandırma seçeneği taşıyan bir veritabanı bağlantı nesnesi için de geçerlidir.

Karar vermek için kullanılabilecek basit bir kural şudur: bir sınıfın toplam alan sayısı beşin üzerindeyse ve bu alanların en az yarısı opsiyonel ise, Builder deseni büyük olasılıkla değer katar. Alan sayısı düşükse veya alanların büyük çoğunluğu zorunluysa, sade bir constructor ya da en fazla bir iki overload yeterlidir. Bu tür kararları örnekler üzerinden pratik yaparak içselleştirmek, tasarım desenlerini ezbere değil sezgiyle uygulamayı öğretir; birebir Java dersleri kapsamında bu tür sınıf tasarımı kararları gerçek proje senaryoları üzerinden birlikte değerlendirilir. Önemli olan, her çok parametreli sınıfa otomatik olarak Builder eklemek değil, sınıfın gerçek kullanım şekline bakıp en sade çözümü seçmektir.

Builder Sadece Bu Örneğe Özgü Değil: Genel Bir Yaratımsal Desen

Buraya kadar verilen örnekler tek bir sınıf üzerinden ilerledi, ama Builder deseninin gerçek değeri tam da burada ortaya çıkıyor: bu desen belirli bir sınıfa veya probleme özgü bir çözüm değil, genel bir creational (yaratımsal) tasarım desenidir. Yani karşınıza çıkan her "çok fazla parametreli, opsiyonel alanları olan nesne" senaryosunda aynı mantığı tekrar tekrar uygulayabilirsiniz. Desen; parametre isimleri, alan sayısı veya iş alanı değiştikçe geçerliliğini kaybetmez, çünkü çözdüğü şey sınıfa özgü bir detay değil, nesne oluşturma sürecinin kendisidir.

Pratikte bu deseni en sık nerede görürsünüz? Bir uygulamanın konfigürasyon nesnelerinde — veritabanı bağlantı ayarları, sunucu parametreleri, loglama seçenekleri gibi çoğu opsiyonel olan alanlarda. HTTP istemci kütüphanelerinde istek (request) nesneleri oluşturulurken de aynı mantık işler: URL zorunludur ama header, timeout, body gibi alanlar duruma göre eklenir. Karmaşık veri modellerinde, özellikle bir nesnenin onlarca alanı olup bunların sadece birkaçının her senaryoda dolu olduğu durumlarda, Builder yine devreye girer. Ortak nokta hep aynıdır: zorunlu ile opsiyonel alanların net biçimde ayrışması gereken, okunabilirliğin kritik olduğu nesne oluşturma süreçleri.

Bu yaygınlık, ekosistemde Builder'ı elle yazmak zorunda kalmadan üretmenizi sağlayan araçların doğmasına da yol açtı. Lombok gibi kütüphaneler, sınıfın üzerine tek bir ek not (annotation) ekleyerek tüm builder metotlarını, iç sınıfı ve build() metodunu sizin yerinize otomatik üretebilir. Bu, günlük geliştirme hızını gerçekten artırır. Ama burada önemli bir uyarı var: aracın ürettiği kodu okuyup mantığını anlayamıyorsanız, o kod sizin için bir kara kutu haline gelir; bir hata aldığınızda veya özelleştirme yapmanız gerektiğinde ilerleyemezsiniz. Bu yüzden önce deseni elle yazıp iç mantığını sindirmek, sonra otomasyon araçlarını kullanmak, tersine göre çok daha sağlam bir öğrenme yoludur. Kendi seviyenizi bu tür yapısal konularda test etmek isterseniz ücretsiz kodlama bilgisi değerlendirmesi ile nerede olduğunuzu görebilirsiniz.

Java Öğreniminde Tasarım Desenlerine Nasıl Geçiş Yapılır?

Builder gibi bir deseni gerçekten anlayıp doğru yerde kullanabilmek, önce sağlam bir OOP temeli gerektirir. Constructor'ların nasıl çalıştığını, encapsulation'ın neden var olduğunu ve bir metodun sınıf içindeki rolünü kavramamış biri için Builder sadece "biraz daha fazla kod yazmak" gibi görünür; oysa mesele kod miktarı değil, nesnenin oluşturulma sürecini kontrol altına almaktır. Bu yüzden tasarım desenlerine geçiş, her zaman temel OOP kavramlarının pekiştirilmesiyle başlamalıdır — aksi halde desen ezberlenir ama ne zaman kullanılacağı anlaşılmaz.

Bu pekiştirme süreci, tek başına kitap okuyarak değil, gerçek kod üzerinde geri bildirim alarak ilerler. Canlı sınıf ortamında bir eğitmenin telescoping constructor'lı bir kodu neden Builder'a çevirdiğini adım adım göstermesi, ya da 1-1 özel ders sürecinde öğrencinin kendi yazdığı sınıfın üzerinden "bu alan neden zorunlu, bu neden opsiyonel" sorusunu birlikte tartışması, kavramı soyut bir tanımdan çıkarıp somutlaştırır. Bu tür bire bir çalışmalar, öğrencinin hazır cevap ezberlemesi yerine benzer bir problemle tekrar karşılaştığında kendi çözümünü kurabilmesini sağlar.

Bu noktada tekrar pratiğinin de payı büyüktür. Berk Akademi'nin öğrenme ekosisteminde yer alan kategori bazlı soru bankaları, öğrencinin OOP ve tasarım desenleri konularını dağınık biçimde değil, konu bazlı ve düzenli olarak tekrar etmesine imkân verir; böylece Builder gibi bir desen tek seferlik bir örnekten ibaret kalmaz, farklı senaryolarla defalarca karşılaşılan bir alışkanlığa dönüşür. Kendi Java bilginizi bu açıdan ölçmek isterseniz Java bilgi testi ile hangi konularda tekrar yapmanız gerektiğini görebilirsiniz.

Son olarak somut bir adım önerisi: kendi kod tabanınızda dört veya daha fazla parametre alan constructor'ları arayın. Her birinin yanına not düşün — hangi alanlar gerçekten zorunlu, hangileri opsiyonel? Bu listeyi çıkardıktan sonra en az birini Builder desenine çevirmeyi deneyin. Bu küçük egzersiz, deseni bir defada kalıcı biçimde öğrenmenizi sağlayacaktır.

Sık Sorulan Sorular

Builder deseni her sınıfa mı uygulanmalı?

Hayır. Az sayıda ve genellikle zorunlu parametresi olan basit sınıflarda Builder gereksiz bir karmaşıklık ekler. Bu desen, opsiyonel alanların çok olduğu, okunabilirliğin constructor çağrısında kaybolduğu durumlarda değer üretir.

Lombok gibi araçlar Builder desenini otomatikleştirir mi?

Evet, Lombok gibi kütüphaneler bir ek not aracılığıyla builder metotlarını otomatik üretebilir. Ancak bu otomasyonu verimli kullanabilmek için altındaki mantığı, yani neden bu yapının kurulduğunu anlamış olmak gerekir.

Builder deseni ile Factory deseni arasındaki fark nedir?

Factory deseni hangi sınıfın örnekleneceğine karar vermeye odaklanır; Builder ise tek bir sınıfın karmaşık ve çok adımlı oluşturulma sürecini yönetmeye odaklanır. Farklı problemleri çözerler ve bazen birlikte de kullanılabilirler.

Kaç parametreden sonra Builder kullanmak mantıklı hale gelir?

Kesin bir sayı yoktur, ancak dört veya daha fazla parametre olduğunda, özellikle bunlardan birkaçı opsiyonelse, telescoping constructor'ların okunabilirliği ciddi biçimde düşer ve Builder değerlendirilmeye başlanmalıdır.

Builder deseni yalnızca Java'ya mı özgüdür?

Hayır, Builder genel bir creational tasarım desenidir ve nesne yönelimli birçok dilde benzer mantıkla uygulanabilir. Java'daki method chaining yaklaşımı, desenin sadece bir uygulama biçimidir.

Method chaining performansı olumsuz etkiler mi?

Pratikte ölçülebilir bir performans kaybı yoktur; her metot çağrısı zaten olağan bir metot çağrısıdır, sadece this döndürerek zincirlenir. Asıl kazanç okunabilirlikte olduğu için performans kaygısı gündeme gelmez.

Builder deseni immutable (değişmez) nesneler için uygun mudur?

Evet, aslında en yaygın kullanım alanlarından biridir. Builder, tüm alanları adım adım topladıktan sonra build() metodunda tek seferde değişmez bir nesne üretmeye izin verir, böylece nesne oluştuktan sonra hiçbir alanı değiştirilemez.

Builder deseni, çok parametreli nesne oluşturma sorununu çözmenin ötesinde, okunabilir ve sürdürülebilir kod yazma alışkanlığının bir parçasıdır. Bu tür tasarım desenlerini OOP temelleriyle birlikte pekiştirmek isteyenler Java özel ders sürecinde konuyu kendi kod örnekleri üzerinden çalışabilir.

Bu içeriğin üretilmesinde yapay zeka araçlarından destek alınmıştır.

İlgili Eğitimler

Berk Keskin — Yazılım Geliştirici ve Eğitmen
Yazar

Berk Keskin Kimdir?

Yazılıma 12 yaşında başladı; bugün öğrencinin seviyesine ve hedefine göre şekillenen sürdürülebilir öğrenme sistemleri tasarlıyor. 300'den fazla kişiye ezber değil, düşünerek kod yazmayı öğretti — Berk Akademi'de izlemeye değil üretmeye dayalı öğrenme kültürünü o kuruyor.

WhatsApp Hemen Ara