Creational — Oluşturucu Desenler
Factory Method
Fabrika Metodu Deseni
Amaç: Nesne oluşturma işini bir metoda devretmek ve hangi sınıfın oluşturulacağına alt sınıfların karar vermesini sağlamak.
Basit Anlatım
Teknik terim yok — günlük hayattan bir benzetme
Bir lojistik şirketi düşünün. Müşteri sadece "Bu paketi teslim edin" der. Şirketin kara yolu şubesi paketi kamyonla, deniz yolu şubesi ise gemiyle gönderir.
Müşteri hangi aracın seçildiğiyle ilgilenmez. Teslimat süreci (paketi al, yükle, gönder, teslim et) her şubede aynıdır; değişen tek şey hangi aracın kullanıldığıdır ve bu kararı her şube kendisi verir.
Günlük hayattan bir örnek daha
Bir pizza zincirinin İstanbul ve Napoli şubeleri var. İkisinde de sipariş süreci aynı: hamuru hazırla, pişir, kutula. Ama İstanbul şubesi "kalın hamurlu", Napoli şubesi "ince hamurlu" pizza üretir. Genel merkez süreci tanımlar, ne üretileceğine şubeler karar verir.
Teknik Anlamı
Bir yazılımcının bakış açısıyla
Factory Method, bir üst sınıfta nesne oluşturmak için bir arayüz (metot) tanımlar, ancak hangi somut sınıfın örnekleneceğine alt sınıfların karar vermesine izin verir.
Katılımcılar
- Product: Oluşturulacak nesnelerin ortak arayüzü (
ITransport). - ConcreteProduct: Somut ürünler (
Truck,Ship). - Creator: Factory metodunu (
CreateTransport()) bildiren ve bu ürünü kullanan iş mantığını içeren soyut sınıf (Logistics). - ConcreteCreator: Factory metodunu override ederek somut ürünü döndüren sınıflar (
RoadLogistics,SeaLogistics).
Çözdüğü problem
Kodun her yerinde new Truck() yazarsanız, yarın gemi taşımacılığı eklediğinizde onlarca yerde if/else yazmak zorunda kalırsınız. Factory Method, new çağrısını tek bir override edilebilir metoda toplar.
Avantajlar
- Creator ile somut ürünler arasında gevşek bağlılık (loose coupling).
- Open/Closed: Yeni ürün türü eklemek için mevcut kodu değiştirmeden yeni bir Creator alt sınıfı yazmak yeterlidir.
- Ürün oluşturma kodu tek bir yerde toplanır (Single Responsibility).
Dezavantajlar
- Her yeni ürün için yeni bir Creator alt sınıfı gerekir; sınıf sayısı artabilir.
switch ile nesne döndürmek) ile karıştırılmamalı. Factory Method'un özü kalıtım ve override'dır.C# ile Uygulama
Adım adım, çalışan kod örneği
Senaryo: Lojistik uygulaması. Teslimat süreci ortak, taşıma aracı şubeye göre değişiyor.
Adım 1 Product arayüzü ve somut ürünler
public interface ITransport
{
string Deliver(string cargo);
}
public class Truck : ITransport
{
public string Deliver(string cargo) => $"'{cargo}' kara yolundan kamyonla gönderildi.";
}
public class Ship : ITransport
{
public string Deliver(string cargo) => $"'{cargo}' deniz yolundan gemiyle gönderildi.";
}Adım 2 Creator: factory metodu ve ortak iş mantığı
PlanDelivery süreci tanımlar ama hangi aracın kullanılacağını bilmez; bunu soyut CreateTransport() metoduna bırakır.
public abstract class Logistics
{
// Factory Method: alt sınıflar hangi ürünün oluşacağına karar verir.
protected abstract ITransport CreateTransport();
// Ortak iş mantığı: ürünün somut tipini bilmeden çalışır.
public void PlanDelivery(string cargo)
{
ITransport transport = CreateTransport();
Console.WriteLine($"[{GetType().Name}] {transport.Deliver(cargo)}");
}
}Adım 3 ConcreteCreator sınıfları
public class RoadLogistics : Logistics
{
protected override ITransport CreateTransport() => new Truck();
}
public class SeaLogistics : Logistics
{
protected override ITransport CreateTransport() => new Ship();
}Adım 4 Kullanım
İstemci yalnızca Logistics soyutlamasını tanır. Hangi şubenin kullanılacağı çalışma zamanında seçilebilir:
Logistics GetLogistics(string region) => region switch
{
"kara" => new RoadLogistics(),
"deniz" => new SeaLogistics(),
_ => throw new ArgumentException("Bilinmeyen bölge")
};
GetLogistics("kara").PlanDelivery("Mobilya");
GetLogistics("deniz").PlanDelivery("Konteyner");Konsol çıktısı
[RoadLogistics] 'Mobilya' kara yolundan kamyonla gönderildi. [SeaLogistics] 'Konteyner' deniz yolundan gemiyle gönderildi.
Kodda dikkat edilmesi gerekenler
PlanDeliverymetodu hiçbir zamannew Truck()veyanew Ship()yazmıyor; somut sınıflardan tamamen bağımsız.- Hava yolu eklemek istersek:
Plane : ITransportveAirLogistics : Logisticsyazarız. Mevcut hiçbir sınıfa dokunmayız.