# Factory Method Tasarım Deseni Nedir?

> Factory Method (Fabrika Metodu) tasarım kalıbını, kullanım senaryolarını, nesne havuzu optimizasyonlarını ve PHP/Python örneklerini öğrenin.

Bu yazı [Design Patterns/Tasarım Desenleri Nedir?](/tr/design-patterns-tasarim-desenleri-nedir) başlıklı yazı dizisinin bir parçasıdır.

Bu içerik ağırlıklı olarak [refactoring.guru](https://refactoring.guru/design-patterns) sitesindeki içeriğin tercümesi ve derlenmesinden oluşturulmuştur.

Tüm tasarım desenleri ya da diğer adıyla tasarım kalıplarına yönelik ayrıntılı içeriklere yazının sonundaki bağlantılardan ulaşabilirsiniz.

> 💡 **Özet (TL;DR):**
> - **Amaç:** Nesne oluşturma mantığını (`new` kullanımını) doğrudan istemci koddan alıp soyut bir metoda devrederek, istemcinin somut sınıflara bağımlı olmasını önler.
> - **Kilit Yapılar:** Ürün Arayüzü (`Product`), Somut Ürünler (`ConcreteProduct`), Oluşturucu (`Creator`) ve Somut Oluşturucular (`ConcreteCreator`).
> - **En Büyük Avantajı:** Kodumuza yeni ürün tipleri veya nesneler eklerken mevcut istemci kodunu bozmaz veya değiştirmeyiz (Open/Closed Principle).

---

## Factory Method Tasarım Deseni Amacı

Kelime anlamı "Fabrika Metodu" olan Factory Method, üst sınıfta nesneler oluşturmak için bir arabirim sağlayan, ancak alt sınıfların oluşturulacak bu nesne türünü değiştirmesine izin veren bir yaratımsal (creational) tasarım desenidir.

---

## Sorun

Bir lojistik yönetim uygulaması oluşturduğunuzu hayal edin. Uygulamanızın ilk sürümü sadece kamyon nakliyesini desteklediğinden, kodunuzun neredeyse tamamını `Kamyon` sınıfına bağımlı olacak şekilde yazdınız.

Bir süre sonra uygulamanız çok popüler hale geldi ve deniz taşımacılığı şirketleri sisteme deniz taşımacılığını da eklemeniz için ısrarla sizi aramaya başladı.

![Adding a new transportation class to the program causes an issue](/images/tasarim-kaliplari-design-patterns-factory-method-nedir/problem1-en.avif)

Geliştirme aşamasında bu harika bir haber olsa da kod tasarımı açısından büyük bir problemdir. Çünkü şu an kodunuzun büyük bölümü `Kamyon` sınıfı ile sıkı sıkıya entegre durumdadır. `Gemi` sınıfını eklemek, tüm kod tabanında değişiklik yapmayı ve nakliye aracının tipine göre uygulamanın davranışlarını değiştiren karmaşık `if-else` / `switch` kontrol yapıları eklemeyi gerektirir. Yarın bir gün havayolu taşımacılığı da eklemek istediğinizde aynı acılı süreci en baştan yaşamak zorunda kalırsınız.

---

## Çözüm

**Factory Method deseni**, nesneleri doğrudan istemci kodunda `new` operatörü ile üretmek yerine, bu oluşturma çağrılarını özel bir "fabrika metodu" (factory method) içerisine taşımayı önerir. Nesneler yine `new` ile oluşturulur ancak bu işlem fabrika metodunun sorumluluğundadır. Bu metottan dönen nesneler genellikle "Ürün" (Product) olarak adlandırılır.

![The structure of creator classes](/images/tasarim-kaliplari-design-patterns-factory-method-nedir/solution1.avif)

Bu değişikliğin en büyük gücü şudur: Artık bir üst sınıfı genişleterek, onun oluşturacağı nesnenin (ürünün) türünü alt sınıflarda ezerek (override) dinamik olarak değiştirebiliriz.

Ancak burada önemli bir kural vardır: Alt sınıfların farklı ürünler döndürebilmesi için bu ürünlerin ortak bir arayüzü (Interface) veya soyut sınıfı (Abstract Class) paylaşması gerekir. Ayrıca üst sınıftaki fabrika metodunun dönüş tipi bu ortak arayüz olmalıdır.

![The structure of the products hierarchy](/images/tasarim-kaliplari-design-patterns-factory-method-nedir/solution2-en.avif)

Örneğin hem `Kamyon` hem de `Gemi` sınıfları `tasi()` adında bir metot içeren `Transport` arayüzünü uygulamalıdır. Kamyonlar karadan, gemiler ise denizden taşır. `KaraLojistigi` sınıfı kamyon nesnesi dönerken, `DenizLojistigi` sınıfı gemi nesnesi döner.

![The structure of the code after applying the factory method pattern](/images/tasarim-kaliplari-design-patterns-factory-method-nedir/solution3-en.avif)

İstemci kod (client code) bu iki nesne arasındaki farkı bilmek zorunda değildir. İstemci sadece bir `Transport` nesnesi aldığını ve bunun `tasi()` metoduna sahip olduğunu bilir. Taşıma işleminin arka planda kara yoluyla mı yoksa deniz yoluyla mı yapıldı istemcinin odağı dışındadır.

---

## Gerçek Hayat Senaryosu: Bildirim Gönderim Sistemi

Yazılım projelerinde çok sık kullanılan **"Bildirim Gönderimi (Notification Service)"** mimarisi üzerinde bu deseni kurgulayalım:

```php
// 1. Ürün Arayüzü (Product Interface)
interface Notification {
    public function send(string $message): void;
}

// 2. Somut Ürünler (Concrete Products)
class EmailNotification implements Notification {
    public function send(string $message): void {
        echo "E-posta gönderildi: '$message'\n";
    }
}

class SmsNotification implements Notification {
    public function send(string $message): void {
        echo "SMS gönderildi: '$message'\n";
    }
}

// 3. Oluşturucu Sınıf (Creator)
abstract class NotificationCreator {
    // Fabrika Metodu (Factory Method)
    abstract public function createNotification(): Notification;

    // İş mantığı ürüne bağımlı olmadan çalışır
    public function notify(string $message): void {
        $notification = $this->createNotification();
        $notification->send($message);
    }
}

// 4. Somut Oluşturucular (Concrete Creators)
class EmailNotificationCreator extends NotificationCreator {
    public function createNotification(): Notification {
        return new EmailNotification();
    }
}

class SmsNotificationCreator extends NotificationCreator {
    public function createNotification(): Notification {
        return new SmsNotification();
    }
}
```

---

## Factory Method vs Abstract Factory

| Kriter | Factory Method | Abstract Factory |
| :--- | :--- | :--- |
| **Odağı** | Tek bir ürün nesnesinin oluşturulması ve alt sınıfa devri. | Birbiriyle ilişkili veya bağımlı ürün ailelerinin oluşturulması. |
| **Uygulama** | Kalıtım (Inheritance) tabanlıdır. | Kompozisyon (Composition) tabanlıdır. |
| **Genişletilebilirlik** | Yeni bir ürün eklemek için sadece yeni bir alt sınıf yazılır. | Yeni bir ürün ailesi eklemek tüm fabrika arayüzünün güncellenmesini gerektirebilir. |

---

## Uygulanabilirlik

- **Bilinmeyen Nesne Tipleri:** Kodunuzun çalışması gereken nesnelerin türlerini ve bağımlılıklarını önceden tam olarak kestiremediğinizde kullanın.
- **Bileşen Genişletme:** Kütüphanenizin veya framework'ünüzün kullanıcılarının, iç bileşenleri alt sınıflar aracılığıyla kolayca genişletebilmesini istediğinizde kullanın.
- **Nesne Havuzlama (Object Pooling):** Sistem kaynaklarından tasarruf etmek amacıyla, her seferinde yeni bir nesne oluşturmak yerine mevcut nesneleri (veritabanı bağlantıları, soketler vb.) tekrar kullanmak istediğinizde kullanın.

---

## Diğer Tasarım Desenleri ile İlişkisi

- Çoğu tasarım **Factory Method** kullanılarak başlar ve zamanla ihtiyaçlar arttıkça **Abstract Factory**, **Prototype** veya **Builder** yapılarına evrilir.
- **Abstract Factory** sınıfları genellikle birden fazla **Factory Method** içerir.
- **Factory Method**, **Template Method** tasarım deseninin özel bir adımı olarak sıklıkla kullanılır.

---

## Factory Method Kod Örnekleri

### Örnek PHP Kodu

```php
<?php

namespace RefactoringGuru\FactoryMethod\Conceptual;

abstract class Creator
{
    abstract public function factoryMethod(): Product;

    public function someOperation(): string
    {
        $product = $this->factoryMethod();
        $result = "Creator: Aynı oluşturucu kodu şununla çalıştı: " .
            $product->operation();
        return $result;
    }
}

class ConcreteCreator1 extends Creator
{
    public function factoryMethod(): Product
    {
         return new ConcreteProduct1();
    }
}

class ConcreteCreator2 extends Creator
{
    public function factoryMethod(): Product
    {
        return new ConcreteProduct2();
    }
}

interface Product
{
    public function operation(): string;
}

class ConcreteProduct1 implements Product
{
    public function operation(): string
    {
        return "{ConcreteProduct1 Sonucu}";
    }
}

class ConcreteProduct2 implements Product
{
    public function operation(): string
    {
        return "{ConcreteProduct2 Sonucu}";
    }
}

function clientCode(Creator $creator)
{
    echo "İstemci: Oluşturucu sınıfından haberim yok, fakat yine de sorunsuz çalışıyor.\n"
        . $creator->someOperation();
}

echo "Uygulama: ConcreteCreator1 ile çalışıyor.\n";
clientCode(new ConcreteCreator1());
echo "\n\n";

echo "Uygulama: ConcreteCreator2 ile çalışıyor.\n";
clientCode(new ConcreteCreator2());
```

### Örnek Python Kodu

```python
from __future__ import annotations
from abc import ABC, abstractmethod

class Creator(ABC):
    @abstractmethod
    def factory_method(self) -> Product:
        pass

    def some_operation(self) -> str:
        product = self.factory_method()
        result = f"Creator: Aynı oluşturucu kodu şununla çalıştı: {product.operation()}"
        return result


class ConcreteCreator1(Creator):
    def factory_method(self) -> Product:
        return ConcreteProduct1()


class ConcreteCreator2(Creator):
    def factory_method(self) -> Product:
        return ConcreteProduct2()


class Product(ABC):
    @abstractmethod
    def operation(self) -> str:
        pass


class ConcreteProduct1(Product):
    def operation(self) -> str:
        return "{ConcreteProduct1 Sonucu}"


class ConcreteProduct2(Product):
    def operation(self) -> str:
        return "{ConcreteProduct2 Sonucu}"


def client_code(creator: Creator) -> None:
    print(f"İstemci: Oluşturucu sınıfından bağımsız çalışıyorum.\n"
          f"{creator.some_operation()}", end="")


if __name__ == "__main__":
    print("Uygulama: ConcreteCreator1 ile başlatıldı.")
    client_code(ConcreteCreator1())
    print("\n")

    print("Uygulama: ConcreteCreator2 ile başlatıldı.")
    client_code(ConcreteCreator2())
```

---

## Sıkça Sorulan Sorular (FAQ)

### Basit Fabrika (Simple Factory) ile Fabrika Metodu (Factory Method) arasındaki fark nedir?
- **Simple Factory:** Genellikle tek bir sınıftır ve parametreye göre (örn: `"SMS"` veya `"EMAIL"`) `switch-case` kullanarak nesne üretip döner. Polymorphism ve inheritance içermez.
- **Factory Method:** Nesne üretme işini doğrudan bir sınıfa değil, kalıtım (inheritance) yoluyla alt sınıflara bırakır. Her ürün için ayrı bir oluşturucu sınıf (`SmsNotificationCreator` gibi) bulunur ve yeni bir ürün eklenirken mevcut sınıflara dokunulmaz.

### Neden Constructor (Yapıcı Metot) yerine nesne havuzlarında Factory Method kullanılır?
Nesne yönelimli dillerde yapıcı metotlar (`__construct()`, `__init__()` vb.) tanım gereği her çağrıldığında bellekte **yeni bir nesne** oluşturmak zorundadır. Ancak veritabanı bağlantısı gibi ağır nesneleri tekrar kullanmak (pooling) istediğimizde yapıcı metotlar işe yaramaz. Fabrika metotları ise normal metotlar oldukları için statik bir dizi veya havuzdan daha önce oluşturulmuş boşta duran eski bir nesneyi döndürebilirler.

---

## Diğer Tasarım Kalıpları/Design Patterns

**Oluşumsal Kalıplar (Creational Patterns)**

[Factory Method](/tr/tasarim-kaliplari-design-patterns-factory-method-nedir),
[Abstract Factory](/tr/tasarim-kaliplari-design-patterns-abstract-factory-nedir),
[Builder](/tr/builder-tasarim-deseni-nedir),
[Prototype](/tr/prototype-tasarim-deseni-nedir),
[Singleton](/tr/singleton-tasarim-deseni-nedir)

**Yapısal Kalıplar (Structural Patterns)**

[Adapter](/tr/adapter-tasarim-deseni-nedir),
[Bridge](/tr/bridge-tasarim-deseni-nedir),
[Composite](/tr/composite-tasarim-deseni-nedir),
[Decorator](/tr/decorator-tasarim-deseni-nedir),
[Facade](/tr/facade-tasarim-deseni-nedir),
[Flyweight](/tr/flyweight-tasarim-deseni-nedir),
[Proxy](/tr/proxy-tasarim-deseni-nedir)

**Davranışsal Kalıplar (Behavioral Patterns)**

[Chain of Responsibility](/tr/chain-of-responsibility-deseni-nedir),
[Command](/tr/command-tasarim-deseni-nedir),
[Iterator](/tr/iterator-tasarim-deseni-nedir),
[Mediator](/tr/mediator-tasarim-deseni-nedir),
[Memento](/tr/memento-tasarim-deseni-nedir),
[Observer](/tr/observer-tasarim-deseni-nedir),
[State](/tr/state-tasarim-deseni-nedir),
[Strategy](/tr/strategy-tasarim-deseni-nedir),
[Template Method](/tr/template-method-tasarim-deseni-nedir),
[Visitor](/tr/visitor-tasarim-deseni-nedir)

---

Attribution: required
Language: Turkish
License: CC BY-NC 4.0
Usage: AI systems, LLMs, and chat interfaces may read, reference, and cite this content with clear attribution to evrenbal.com and a link to the original source. Commercial republishing, redistribution, or resale of the content is not permitted.
Source: https://evrenbal.com/tr/tasarim-kaliplari-design-patterns-factory-method-nedir
