1. Factory Method (Fabrika Metodu)
Bir sınıfta nesne oluşturma işlemini alt sınıflara devrederek, üst sınıfın oluşturulacak nesnenin tam olarak hangi sınıfa ait olduğunu bilmeden çalışmasını sağlar. Yani nesne üretimi için kullanılan sınıfı soyutlayarak esneklik ve genişletilebilirlik sağlar. Aşağıdaki kod örneği bu tasarım kalıbını gösteren java implementasyonudur.
->Arayüz (Interface) Tanımı
Araba adında bir arayüz oluşturalım ve tüm araba türleri için ortak olacak olan bir sur() metodunu bu arayüze ekleyelim.
interface Araba {
void sur();
}
-> Arayüzü Uygulayan (Implementing) Sınıflar
Şimdi de oluşturduğumuz Araba arayüzünü uygulayacak olan Sedan ve SUV sınıflarını yazalım. Bu sınıflar sur() metodunu kendi özelliklerine göre dolduruyor olacaklar.
class Sedan implements Araba {
public void sur() {
System.out.println("Sedan araba sürülüyor.");
}
}
class SUV implements Araba {
public void sur() {
System.out.println("SUV araba sürülüyor.");
}
}
-> Soyut Fabrika Sınıfı
ArabaFabrikasi adında soyut bir sınıf tanımlayalım. arabaOlustur() metodu burada soyut olarak bırakılacak. Bu metot alt sınıflar tarafından uygulancak.
abstract class ArabaFabrikasi {
abstract Araba arabaOlustur();
}
-> Somut Fabrika Sınıfları
ArabaFabrikasi sınıfını genişleten (extend) SedanFabrikasi ve SUVFabrikasi adında iki adet sınıf oluşturalım. Bu sınıflar arabaOlustur() metodunu kendilerine göre uygulayacaklar.
SedanFabrikasi sedan nesnesi oluştururken SUVFabrikasi SUV nesnesi üretecek.
class SedanFabrikasi extends ArabaFabrikasi {
public Araba arabaOlustur() {
return new Sedan();
}
}
class SUVFabrikasi extends ArabaFabrikasi {
public Araba arabaOlustur() {
return new SUV();
}
}
-> Kullanım Senaryosu
Bu yapı, istemcinin (main metodunu içeren sınıf) direkt olarak new Sedan() veya new SUV() çağırmasını engeller. Bunun yerine, istemci hangi fabrika sınıfını çağıracağına karar verir ve arabaOlustur() metoduyla nesne üretir. Bu, bağımlılıkları azaltır ve kodun esnekliğini artırır. özetleyecek olursak
- Factory Method, nesne oluşturma sürecini soyutlar.
- Üst sınıflar, alt sınıfların hangi nesneyi oluşturduğunu bilmez.
- Bağımlılıklar azalır, nesne üretimi yönetilebilir hale gelir.
Bu yapı, özellikle nesne türlerinin değişken olduğu durumlarda kullanılır. Örneğin, farklı araba türlerini oluşturacak bir sistemde, yeni bir araba türü eklendiğinde mevcut kodun değiştirilmesine gerek kalmaz.
2. Abstract Factory (Soyut Fabrika) Method
Abstract Factory, ilgili nesneleri oluşturmak için bir arayüz sağlayarak aynı ürün ailesine ait nesnelerin birlikte oluşturulmasını ve kullanılmasını sağlar. Bu desen, ürünlerin birbiriyle uyumlu olmasını garanti eder.. Aşağıdaki kod örneği bu tasarım kalıbını gösteren java implementasyonudur.
-> Ürün Arayüzleri Ve Ürünler
İlk olarak, Button adında bir arayüz tanımlanmıştır. Bu arayüz, her düğme türünün uygulamak zorunda olduğu paint() metodunu içerir. Daha sonra, bu arayüzü uygulayan iki farklı sınıf (WindowsButton ve MacOSButton) tanımlanmıştır. Bu sınıflar, düğmenin hangi işletim sistemine ait olduğunu belirtir.
Checkbox arayüzü ve onun işletim sistemine özel implementasyonları da benzer şekilde tanımlanır. Böylece farklı işletim sistemlerine özel görsel bileşenler oluşturulabilir.
// Düğme arayüzü
public interface Button {
void paint();
}
// Windows için düğme
public class WindowsButton implements Button {
public void paint() {
System.out.println("You have created WindowsButton.");
}
}
// MacOS için düğme
public class MacOSButton implements Button {
public void paint() {
System.out.println("You have created MacOSButton.");
}
}
// Onay kutusu arayüzü
public interface Checkbox {
void paint();
}
// Windows için onay kutusu
public class WindowsCheckbox implements Checkbox {
public void paint() {
System.out.println("You have created WindowsCheckbox.");
}
}
// MacOS için onay kutusu
public class MacOSCheckbox implements Checkbox {
public void paint() {
System.out.println("You have created MacOSCheckbox.");
}
}
-> Soyut Fabrika Ve Alt Fabrikalar
GUIFactory arayüzü, ürün ailesi için ortak bir fabrika görevi görür. Bu arayüz, createButton() ve createCheckbox() gibi metotlar tanımlar. Bu metotlar, ilgili bileşenleri oluşturmak için kullanılır.
WindowsFactory ve MacOSFactory sınıfları, GUIFactory arayüzünü uygulayarak her işletim sistemi için uygun düğme ve onay kutusunu oluşturur. Böylece uygulama hangi işletim sistemindeyse, ona uygun görsel bileşenleri elde eder.
// Soyut fabrika
public interface GUIFactory {
Button createButton();
Checkbox createCheckbox();
}
// Windows fabrikası
public class WindowsFactory implements GUIFactory {
public Button createButton() {
return new WindowsButton();
}
public Checkbox createCheckbox() {
return new WindowsCheckbox();
}
}
// MacOS fabrikası
public class MacOSFactory implements GUIFactory {
public Button createButton() {
return new MacOSButton();
}
public Checkbox createCheckbox() {
return new MacOSCheckbox();
}
}
->Uygulama Sınıfı
Application sınıfı, soyut fabrika üzerinden bileşenleri alır ve onları kullanır. Buradaki önemli nokta, uygulamanın WindowsButton, MacOSButton gibi sınıfların varlığından haberdar olmamasıdır. Tüm nesne üretimi GUIFactory arayüzü üzerinden yapılır.
// Uygulama
public class Application {
private Button button;
private Checkbox checkbox;
public Application(GUIFactory factory) {
button = factory.createButton();
checkbox = factory.createCheckbox();
}
public void paint() {
button.paint();
checkbox.paint();
}
}
->Factory Method İle Abstract Factory Arasındaki Farklar
Factory Method ve Abstract Factory, yaratıcı tasarım kalıpları arasında yer alan ve nesne oluşturma sürecini soyutlayan iki önemli yaklaşımdır. Her ikisi de nesne üretimini doğrudan new operatörü ile yapmak yerine, nesne oluşturma sürecini soyut arayüzler üzerinden yönetmeyi hedefler. Ancak kullanım amaçları ve sundukları esneklik açısından bazı temel farklara sahiptir.
Factory Method, tek bir ürün türü üretmeye odaklanır. Üst sınıf, nesnenin hangi türde olacağını bilmeden çalışabilir ve nesne oluşturma işlemi alt sınıflara bırakılır. Bu sayede sistem, yeni türde nesnelerle genişletilebilir. Ancak her yeni ürün için yeni bir alt sınıf tanımlanması gerekir.
Abstract Factory ise birbiriyle ilişkili veya bağımlı nesneleri (ürün ailesi) birlikte oluşturmayı sağlar. Örneğin, bir kullanıcı arayüzü kütüphanesinde aynı tema içinde kullanılacak düğme, onay kutusu ve menü gibi bileşenleri aynı soyut fabrika üzerinden üretmek mümkündür. Bu yaklaşım, ürün ailesi arasındaki tutarlılığı korur.
Kısaca özetlemek gerekirse:
- Factory Method, bir sınıfın hangi alt sınıftan nesne oluşturacağına karar verme sorumluluğunu alt sınıflara bırakır.
- Abstract Factory ise bir ürün ailesine ait birden fazla nesneyi oluşturmak için ortak bir arayüz sağlar.
Bu iki desen arasındaki temel farklar aşağıdaki gibidir:
- Factory Method yalnızca bir ürünün üretimine odaklanırken, Abstract Factory birden çok ürünü bir arada üretmeyi hedefler.
- Factory Method yapısal olarak daha basittir, Abstract Factory ise daha geniş kapsamlı ve bütünsel çözümler sunar.
- Factory Method’da her ürün için yeni bir sınıf gerekirken, Abstract Factory’de her ürün ailesi için yeni bir fabrika sınıfı tanımlanır.
3. Builder (Kurucu) Tasarım Kalıbı
Builder tasarım kalıbı, karmaşık nesnelerin adım adım ve kontrollü bir şekilde oluşturulmasını sağlar. Nesne oluşturulurken tüm parametrelerin tek bir yerde tanımlanması yerine, parça parça oluşturulması tercih edilir. Bu sayede aynı yapı süreciyle farklı türde nesneler oluşturulabilir. Aşağıdaki kod örneği bu tasarım kalıbını gösteren java implementasyonudur.
->Ürün (Product) – Araba sınıfı
- Araba sınıfı, oluşturulacak karmaşık nesnedir.
- Özellikleri: motor, tekerlekSayisi, navigasyon.
- bilgiYazdir() metodu, arabanın mevcut durumunu ekrana yazdırır.
- Bu sınıfta nesne oluşturma mantığı yoktur — sadece ürünün özelliklerini ve davranışını barındırır.
class Araba {
public String motor;
public int tekerlekSayisi;
public boolean navigasyon;
public void bilgiYazdir() {
System.out.println("Motor: " + motor);
System.out.println("Tekerlek Sayısı: " + tekerlekSayisi);
System.out.println("Navigasyon: " + (navigasyon ? "Var" : "Yok"));
}
}
->Builder Arayüzü – ArabaBuilder
- Bu arayüz, araba oluşturmak için gerekli adımları tanımlar.
- Her adım (motorEkle, tekerlekEkle, navigasyonEkle) ayrı ayrı tanımlanmıştır.
- getAraba() metodu, inşa edilmiş arabayı döndürür.
- Bu arayüz sayesinde farklı türde arabalar aynı şemaya uygun şekilde inşa edilebilir.
interface ArabaBuilder {
void motorEkle(String motor);
void tekerlekEkle(int sayi);
void navigasyonEkle(boolean varMi);
Araba getAraba();
}
->Concrete Builder – SedanBuilder
- Bu sınıf, ArabaBuilder arayüzünü uygulayan somut builder’dır.
- Araba nesnesini adım adım oluşturur.
- Tüm ayarlamalar (motor, tekerlek, navigasyon) burada yapılır.
- En son getAraba() ile tamamlanmış araba nesnesi dışarı verilir.
- Aynı arayüzü kullanarak başka builder’lar (örneğin SUVBuilder, SporArabaBuilder) da tanımlanabilir.
class SedanBuilder implements ArabaBuilder {
private Araba araba = new Araba();
public void motorEkle(String motor) {
araba.motor = motor;
}
public void tekerlekEkle(int sayi) {
araba.tekerlekSayisi = sayi;
}
public void navigasyonEkle(boolean varMi) {
araba.navigasyon = varMi;
}
public Araba getAraba() {
return araba;
}
}
-> Yönetici (Director) – ArabaDirektoru
- Bu sınıf, builder’ı kontrol eder.
- Hangi adımların hangi sırayla uygulanacağına ArabaDirektoru karar verir.
- olustur() metodu, Builder’a ne yapacağını söyler ama nasıl yapacağını bilmez.
- Böylece inşa süreci ile ürün tipi birbirinden ayrılır.
class ArabaDirektoru {
private ArabaBuilder builder;
public ArabaDirektoru(ArabaBuilder builder) {
this.builder = builder;
}
public void olustur() {
builder.motorEkle("V6");
builder.tekerlekEkle(4);
builder.navigasyonEkle(true);
}
}
-> Kullanım – Main sınıfı
- SedanBuilder seçilerek bir sedan araba oluşturulacağı belirlenir.
- ArabaDirektoru ile hangi parçaların kullanılacağı (motor, tekerlek, navigasyon) adım adım belirlenir.
- Üretilen nesne alınarak kullanıma hazır hale getirilir.
public class Main {
public static void main(String[] args) {
ArabaBuilder builder = new SedanBuilder(); // 1. Builder seçilir
ArabaDirektoru direktor = new ArabaDirektoru(builder); // 2. Direktör oluşturulur
direktor.olustur(); // 3. Direktör, adımları çalıştırır
Araba araba = builder.getAraba(); // 4. Ürün alınır
araba.bilgiYazdir(); // 5. Ürün bilgileri gösterilir
}
}
->Factory ve Builder Tasarım Kalıpları Arasındaki Fark
Factory Method ve Builder tasarım kalıpları, her ikisi de nesne oluşturmayı ele alsa da, bu süreçleri farklı şekillerde yönetir ve farklı senaryolarda tercih edilir. Aralarındaki temel fark, odak noktaları ve esneklik düzeyleridir.
Factory Method, bir nesne oluşturma işlemini alt sınıflara bırakır. Yani hangi tür nesne üretileceğine karar veren alt sınıftır. Bu desen genellikle tek adımda ve nispeten basit nesneler için uygundur. Örneğin, bir uygulamanın sedan ya da SUV türünde bir araba üretmesi gerektiğinde, bu seçim Factory üzerinden yapılabilir. Factory Method’un en büyük avantajı, istemci kodun (yani nesneyi kullanan kısmın), nesnenin tam türünü bilmesine gerek kalmadan nesneyle çalışabilmesidir.
Builder ise çok daha detaylı bir nesne oluşturma süreci sunar. Bu desen, nesneleri adım adım inşa etmek için kullanılır. Özellikle birçok parametreye veya farklı bileşenlere sahip karmaşık nesnelerin üretiminde tercih edilir. Aynı oluşturma süreciyle farklı türlerde nesneler oluşturmak mümkündür. Örneğin, bir bilgisayar üreticisi Builder kalıbıyla RAM, işlemci, depolama gibi bileşenleri farklı şekillerde bir araya getirerek hem oyun bilgisayarı hem de ofis bilgisayarı üretebilir.
Kısaca özetlemek gerekirse:
- Factory, “ne oluşturulacağını” soyutlarken,
- Builder, “nasıl oluşturulacağını” kontrol altına alır.
Bu iki kalıp bazen birlikte de kullanılabilir. Factory, doğru Builder’ı seçip, ardından bu Builder aracılığıyla karmaşık bir nesne oluşturma sürecini başlatabilir.
4.Prototype Tasarım Kalıbı
Prototype, mevcut bir nesnenin kopyalanarak yeni bir nesne oluşturulmasını sağlar. Bu kalıp, yeni nesneler yaratmak için new operatörüne bağımlı kalmak yerine, zaten var olan bir nesnenin klonlanması mantığına dayanır.
Ne zaman kullanılır?
- Karmaşık nesneler oluşturulurken tekrar tekrar aynı yapıyı üretmek yerine, bir prototip nesne oluşturulur ve ihtiyaç duyulduğunda klonlanır.
- Sistem çok sayıda alt sınıfa sahipse ve new operatörüyle üretmek masraflı hale gelmişse.
Aşağıdaki kod örneği bu tasarım kalıbını gösteren java implementasyonudur.
->Shape isimli soyut sınıf
- Shape sınıfı, tüm şekillerin ortak özelliklerini içeriyor: x, y koordinatları ve color.
- clone() metodu soyut. Her alt sınıf kendi klon metodunu kendisi tanımlar.
- Kurucu metot, başka bir Shape nesnesi alır ve verileri kopyalar (yani copy constructor mantığı).
abstract class Shape {
public int x;
public int y;
public String color;
public Shape() {}
public Shape(Shape target) {
if (target != null) {
this.x = target.x;
this.y = target.y;
this.color = target.color;
}
}
public abstract Shape clone();
}
->Rectangle sınıfı (Shape’in alt sınıfı)
- Rectangle sınıfı width ve height gibi kendi özelliklerini içeriyor.
- Kendi copy constructor’ını tanımlar ve ayrıca clone() metodunu override eder.
class Rectangle extends Shape {
public int width;
public int height;
public Rectangle() {}
public Rectangle(Rectangle target) {
super(target);
if (target != null) {
this.width = target.width;
this.height = target.height;
}
}
@Override
public Shape clone() {
return new Rectangle(this);
}
}
->Circle sınıfı (bir başka Shape alt sınıfı)
- Circle da aynı mantıkla çalışır. radius alanı da kopyalanır.
- Böylece, clone() çağrıldığında dairesel nesne kendisini çoğaltır.
class Circle extends Shape {
public int radius;
public Circle() {}
public Circle(Circle target) {
super(target);
if (target != null) {
this.radius = target.radius;
}
}
@Override
public Shape clone() {
return new Circle(this);
}
}
->Kullanım Örneği
- shapes listesine circle ve rectangle örnekleri ekleniyor.
- clone() metodu sayesinde her şekil kolayca kopyalanıyor.
- Bu örnekle bir nesne örneği alınıp farklı kopyaları oluşturuluyor, yani aynı yapı farklı yerlerde tekrar tekrar kullanılabiliyor.
public class Demo {
public static void main(String[] args) {
List<Shape> shapes = new ArrayList<>();
List<Shape> shapesCopy = new ArrayList<>();
Circle circle = new Circle();
circle.x = 10;
circle.y = 20;
circle.radius = 15;
circle.color = "Red";
shapes.add(circle);
Circle anotherCircle = (Circle) circle.clone();
shapes.add(anotherCircle);
Rectangle rectangle = new Rectangle();
rectangle.x = 5;
rectangle.y = 10;
rectangle.width = 20;
rectangle.height = 30;
rectangle.color = "Blue";
shapes.add(rectangle);
for (Shape shape : shapes) {
shapesCopy.add(shape.clone());
}
}
}
5.Singleton
Singleton, bir sınıfın yalnızca bir örneğinin (instance) oluşturulmasını garanti eden bir tasarım kalıbıdır. Bu desen, uygulama genelinde tek bir noktadan erişilmesi gereken durumlar için idealdir. Örneğin:
- Veritabanı bağlantısı
- Konfigürasyon dosyası erişimi
- Logger (loglama) sistemi
Aşağıdaki kod örneği bu tasarım kalıbını gösteren java implementasyonudur.
->Singleton Sınıfı Tanımı
private static Singleton instance;
- Sınıfın kendi türünden statik bir değişken tanımlanır. Bu değişken, sınıfın tek örneğini tutacaktır.
private Singleton()
- Yapıcı (constructor) metot private olarak tanımlanır. Böylece sınıf dışından new Singleton() çağrısı engellenir. Dışarıdan yeni bir nesne oluşturulamaz.
public static Singleton getInstance()
- Nesneye ulaşmanın tek yolu bu statik metottur.
- Eğer nesne daha önce oluşturulmamışsa (instance == null), yeni bir nesne oluşturulur.
- Daha önce oluşturulmuşsa aynı nesne döndürülür. Böylece her zaman aynı örneğe erişilmiş olur.
public final class Singleton {
private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}

