Command Pattern Nedir? PHP ile Uygulama

 


Command Pattern (Komut Tasarım Deseni), bir isteği (komutu) nesne olarak paketlemenizi sağlar. Yani, bir işlemi gerçekleştirmek isteyen kod ile bu işlemi uygulayan kodu birbirinden ayırır.

Bu desenle; işlemleri sıraya alabilir, geri alabilir (undo), kaydedebilir ya da farklı zamanlarda çalıştırmak üzere bekletebilirsiniz.

“Ne yapılacağını bir nesneye dönüştür” felsefesiyle çalışır.


Ne İçin Kullanılır?

  • Komutları sıraya koymak

  • Geri alınabilir (undo/redo) sistemler yapmak

  • İstekleri loglamak ya da daha sonra çalıştırmak

  • Arayüz veya buton işlemlerini soyutlamak

  • Görevleri (task/job) planlamak


Gerçek Hayatta Nerede Kullanılır?

  • Undo/Redo sistemleri (örneğin Photoshop, Word)

  • Queue sistemleri (örn. Laravel Job/Queue)

  • Makro komutlar (birden fazla işlemi zincirlemek)

  • Uzaktan kumanda uygulamaları

  • Menü ya da buton tıklamaları



PHP ile Command Pattern Uygulaması

Senaryo: Bir metin düzenleyicimiz var. Kullanıcı "Kopyala", "Yapıştır" ve "Geri Al" işlemleri yapabiliyor.

1. Komut (interface)

<?php
interface Command {
public function execute();
}


2. Alıcı (Receiver) Sınıf

<?php
class Editor {
public function copy() {
echo "Metin kopyalandı.\n";
}

public function paste() {
echo "Metin yapıştırıldı.\n";
}

public function undo() {
echo "Son işlem geri alındı.\n";
}
}


3. Komut Sınıfları

<?php
class CopyCommand implements Command {
private $editor;

public function __construct(Editor $editor) {
$this->editor = $editor;
}

public function execute() {
$this->editor->copy();
}
}

class PasteCommand implements Command {
private $editor;

public function __construct(Editor $editor) {
$this->editor = $editor;
}

public function execute() {
$this->editor->paste();
}
}

class UndoCommand implements Command {
private $editor;

public function __construct(Editor $editor) {
$this->editor = $editor;
}

public function execute() {
$this->editor->undo();
}
}


4. Komutları Yöneten (Invoker) Sınıf

<?php
class Button {
private $command;

public function __construct(Command $command) {
$this->command = $command;
}

public function click() {
$this->command->execute();
}
}



Kullanım:

<?php
$editor = new Editor();

$copyButton = new Button(new CopyCommand($editor));
$pasteButton = new Button(new PasteCommand($editor));
$undoButton = new Button(new UndoCommand($editor));

$copyButton->click();
$pasteButton->click();
$undoButton->click();


Çıktı:

Metin kopyalandı.
Metin yapıştırıldı.
Son işlem geri alındı.



Avantajları

  • Komutlar arasında gevşek bağlılık sağlar (loose coupling)

  • Geri alma, kaydetme, kuyruklama yapılabilir

  • Yeni komutlar kolayca eklenebilir

  • Arayüzler ile kodun mantığını birbirinden ayırır


Ekstra Bilgi:

Command desenini Laravel gibi modern framework'lerde şu alanlarda görebilirsin:

  • php artisan make:command

  • dispatch(new SendEmailJob())

  • Form işlemleri ve Button Click Event handler sistemleri














 

Builder Pattern Nedir? PHP ile Anlaşılır Uygulama

 

Builder Pattern (Kurucu Desen), karmaşık nesnelerin adım adım oluşturulmasına olanak sağlar. Bu sayede nesnenin nasıl oluşturulacağı detaylarından bağımsız bir şekilde, farklı konfigürasyonlarla nesneler üretilebilir.

“Bir nesne nasıl oluşturulacak?” sorusunu çözer.


Ne İçin Kullanılır?

  • Karmaşık nesnelerin oluşturulmasını kontrol altına almak

  • Aynı oluşturma süreciyle farklı çeşitlerde nesneler üretmek

  • Nesne oluşturma kodunu sınıfın dışına taşımak

  • Yapıcı fonksiyonlara (constructor) çok fazla parametre geçmeyi engellemek

 

Nerelerde Kullanılır?

  • PDF veya rapor üretici sınıflar

  • Form builder (örneğin HTML form oluşturucular)

  • SQL query builder (Laravel Query Builder gibi)

  • Mail veya mesaj şablon sistemleri

  • API isteği oluşturan sınıflar



PHP ile Builder Pattern Uygulaması

Senaryo: Kullanıcının bilgisini tutan bir User nesnesi oluşturmak istiyoruz. Bu nesne opsiyonel alanlara sahip olabilir.

1. Ürün sınıfı (Product)


<?php
class User {
public $name;
public $email;
public $age;

public function showInfo() {
echo "Ad: {$this->name}, Email: {$this->email}, Yaş: {$this->age}\n";
}
}


2. Builder sınıfı


<?php
class UserBuilder {
private $user;

public function __construct() {
$this->user = new User();
}

public function setName($name) {
$this->user->name = $name;
return $this;
}

public function setEmail($email) {
$this->user->email = $email;
return $this;
}

public function setAge($age) {
$this->user->age = $age;
return $this;
}

public function build() {
return $this->user;
}
}


Kullanım:


<?php
$builder = new UserBuilder();
$user = $builder->setName("Ali")
->setEmail("ali@example.com")
->setAge(28)
->build();

$user->showInfo();


Çıktı:


Ad: Ali, Email: ali@example.com, Yaş: 28


Avantajları

  • Kod okunabilirliğini artırır (method chaining)

  • Yapıcıda çok fazla parametre geçme sorununu çözer

  • Gereksiz bağımlılıkları azaltır

  • Test etmeyi kolaylaştırır























PHP ile Facade Pattern: Karmaşık Sistemleri Basitleştir

 


Facade Pattern (Cephe/Sadeleştirici Desen), karmaşık sistemleri basit bir arayüzle dış dünyaya sunmak için kullanılır.

Kullanıcıya birden fazla sınıfla uğraşmak yerine, tek bir sınıf üzerinden kolay erişim imkânı sağlar.


Neden Kullanılır?

  • Karmaşık alt sistemleri bir arayüz altında toplamak

  • Kullanıcıdan teknik detayları saklamak

  • Kodun okunabilirliğini ve bakımını artırmak


Nerelerde Kullanılır?

  • Laravel’deki Facade sınıfları (Cache::put(), Mail::send(), DB::table())

  • API istemcileri (Google, Stripe, Mailchimp gibi servislerin facade sınıfları)

  • Karmaşık sınıf yapılarının soyutlanmasında (örneğin medya oynatıcı, sipariş işlemleri)




PHP ile Facade Pattern Örneği

Senaryo: Bir video oynatma sistemi. Arka planda birçok sınıf var ama kullanıcı sadece VideoPlayer sınıfını kullanacak.

1. Alt sistem sınıfları:

<?php
class FileLoader {
public function load($filename) {
echo "Dosya yüklendi: $filename\n";
}
}

class VideoDecoder {
public function decode($filename) {
echo "Video çözüldü: $filename\n";
}
}

class AudioManager {
public function enableAudio() {
echo "Ses açıldı\n";
}
}



2. Facade sınıfı:


<?php
class VideoPlayer {
protected $fileLoader;
protected $decoder;
protected $audio;

public function __construct() {
$this->fileLoader = new FileLoader();
$this->decoder = new VideoDecoder();
$this->audio = new AudioManager();
}

public function play($filename) {
$this->fileLoader->load($filename);
$this->decoder->decode($filename);
$this->audio->enableAudio();
echo "Video oynatılıyor: $filename\n";
}
}



Kullanım:

<?php
$player = new VideoPlayer();
$player->play("film.mp4");


Çıktı:


Dosya yüklendi: film.mp4  
Video çözüldü: film.mp4
Ses açıldı
Video oynatılıyor: film.mp4


Avantajları

  • Karmaşık işlemleri kullanıcıdan gizler

  • Controller/Service tarafında kod karmaşasını azaltır

  • Daha sade, okunabilir ve sürdürülebilir yapı sağlar

  • Test yazarken kolayca izole edilebilir


Dezavantajları

  • Aşırı kullanım, sistemi gereksiz soyut hale getirebilir

  • Alt sistemlere erişimi tamamen gizlerse, bazı özel işlemler zorlaşabilir


Facade vs Diğer Desenler

DesenAmaç
StrategyFarklı algoritmaları değiştirmek
DecoratorDinamik olarak özellik eklemek
FacadeKarmaşık yapıyı basitleştirip sarmalamak


Özet

  • Facade Pattern, sistemdeki çoklu işlemleri sadeleştirerek tek bir arayüz ile sunmanı sağlar.

  • Laravel, bu deseni birçok yerde kullanır (örneğin: DB::table(), Log::info())

  • Kodun okunabilirliğini artırır, bakım maliyetini azaltır.


Decorator Pattern: Esnek ve Katmanlı Geliştirme

 


Decorator Pattern (Süsleyici Tasarım Deseni)
, mevcut bir nesnenin davranışını değiştirmeden, ona yeni özellikler eklememizi sağlar.

Yani sınıfı değiştirmeden, onu sarmalayarak (wrap) yeni işlevler kazandırırız.

Bu desen, özellikle katmanlı sistemlerde ya da bir işleme farklı davranışlar dinamik olarak eklemek istediğimizde kullanılır.


Neden Kullanılır?

  • Sınıfın içeriğini değiştirmeden işlevini genişletmek için

  • Kalıtım yerine bileşen kullanarak daha esnek kodlama yapmak için

  • Her ihtiyaca özel sınıf türetmek yerine, birleştirilebilir sınıflar yaratmak için


Gerçek Hayatta Kullanım Örnekleri

  • Laravel'de middleware sistemi (her request katman katman işlenir)

  • Logging sistemleri (veriye önce dosya logu, sonra veritabanı logu eklenebilir)

  • Online sipariş sistemleri (ürüne ekstra sos, boyut, vb. eklentiler)

  • HTML render işlemleri (bir metni bold, italic, underline gibi süslemek)



PHP ile Uygulamalı Örnek

Senaryo: Basit bir kahve sipariş sistemine eklemeler yapmak istiyoruz.


1. Interface

<?php
interface Coffee {
public function cost(): int;
public function description(): string;
}


2.Temel kahve sınıfını oluşturalım:


<?php
class BasicCoffee implements Coffee {
public function cost(): int {
return 10;
}

public function description(): string {
return "Sade Kahve";
}
}


3.Decorator sınıfı:


<?php
abstract class CoffeeDecorator implements Coffee {
protected $coffee;

public function __construct(Coffee $coffee) {
$this->coffee = $coffee;
}
}


4.Yeni özellikler ekleyen süsleyiciler:


<?php
class MilkDecorator extends CoffeeDecorator {
public function cost(): int {
return $this->coffee->cost() + 3;
}

public function description(): string {
return $this->coffee->description() . ", Süt";
}
}

class SugarDecorator extends CoffeeDecorator {
public function cost(): int {
return $this->coffee->cost() + 1;
}

public function description(): string {
return $this->coffee->description() . ", Şeker";
}
}



Kullanımı:

<?php
$coffee = new BasicCoffee();
$coffee = new MilkDecorator($coffee);
$coffee = new SugarDecorator($coffee);

echo $coffee->description(); // Sade Kahve, Süt, Şeker
echo $coffee->cost(); // 14



Avantajları

  • Kod tekrarını azaltır

  • Kalıtım yerine kompozisyon kullanır

  • Yeni işlevleri eski sınıfı değiştirmeden eklemenizi sağlar

  • Dinamik olarak davranış eklenebilir (çalışma anında)


Özet

  • Decorator Pattern, kodunuzu katmanlara bölerek esnek ve sürdürülebilir hale getirir.

  • Laravel, Symfony gibi framework’lerde sıkça kullanılır.

  • Karmaşık if-else yapılarından kaçınmak için oldukça idealdir.














OCP (Open/Closed Principle) Nedir?


Açık/Kapalı Prensibi, SOLID prensiplerinden biridir.

Tanım: “Bir yazılım bileşeni (sınıf, modül, fonksiyon), geliştirmeye açıkdeğişikliğe kapalı olmalıdır.”


Ne Demek Bu?

Yani mevcut bir sınıfın içini değiştirmeden, yeni özellikler ekleyebilmeliyiz.


(Kötü Örnek)

Yeni bir ödeme yöntemi eklemek istiyorsak sınıfın içine yine elseif eklememiz gerekir 

→ bu değişiklik demektir.


<?php
//Payment.php
class Payment {
public function pay($type) {
if ($type == 'credit') {
echo "Kredi kartı ile ödeme yapıldı";
} elseif ($type == 'paypal') {
echo "PayPal ile ödeme yapıldı";
}
}
}


Doğru OCP Kullanımı (PHP ile)

Adım 1: Önce bir Interface tanımlayalım:


<?php
interface PaymentMethod {
public function pay();
}


Adım 2: Her ödeme tipi kendi sınıfı içinde olsun:


<?php
class CreditCardPayment implements PaymentMethod {
public function pay() {
echo "Kredi kartı ile ödeme yapıldı";
}
}

class PaypalPayment implements PaymentMethod {
public function pay() {
echo "PayPal ile ödeme yapıldı";
}
}


Adım 3: Ana sınıf artık dışarıdan hangi strateji verilirse onu çalıştırır:


<?php
class PaymentProcessor {
private $paymentMethod;

public function __construct(PaymentMethod $method) {
$this->paymentMethod = $method;
}

public function process() {
$this->paymentMethod->pay();
}
}


Kullanım:


<?php
$payment = new PaymentProcessor(new PaypalPayment());
$payment->process(); // PayPal ile ödeme yapıldı

$payment = new PaymentProcessor(new CreditCardPayment());
$payment->process(); // Kredi kartı ile ödeme yapıldı

Nerelerde Kullanılır?

  • Laravel’de ödeme sistemleri, bildirim sistemleri (Mail/SMS/Slack)

  • E-ticaret sistemlerinde kampanya/indirim algoritmaları

  • Oyun geliştirmede puanlama/ödül sistemleri

  • Çok katmanlı yazılımlarda strateji/desen uygulamalarında


Avantajları:

  • Sınıflarınız daha sade olur.

  • Kod tekrarını azaltır.

  • Test yazmak kolaylaşır.

  • Yeni ihtiyaçlar için eski kodu bozmadan genişletebilirsiniz.


Özet:

  • Kodunuzu yazarken şunu sorun:
    "Bu sınıfa dokunmadan, yeni bir davranış nasıl eklerim?"

  • İşte bu düşünce sizi OCP’ye yaklaştırır



Repository Pattern Nedir? Temiz Veri Katmanı

 



Repository Pattern, veritabanı işlemlerini (CRUD – Create, Read, Update, Delete) uygulama mantığından ayırmak için kullanılan bir tasarım desenidir.

Basitçe:

Kodun içinde DB::table() ya da Model::find() gibi veritabanı işlemlerini doğrudan yazmak yerine, tüm bu işlemleri ayrı bir sınıfta (repository) toplarız.


Neden Kullanılır?

  1. Kodun okunabilirliğini artırır.

  2. Veritabanı işlemlerini merkezileştirir.

  3. Test yazmayı kolaylaştırır (mock edilebilir).

  4. Bir ORM’den diğerine geçişte kolaylık sağlar.

  5. Controller'ları sade tutar.



Gerçek Hayat Örneği

Diyelim ki bir blog sistemimiz var ve Post veritabanı tablosuna erişmemiz gerekiyor.
Repository pattern ile veritabanı işlemlerini şu şekilde soyutlarız:


1. PostRepository Interface


<?php
//PostRepositoryInterface.php
interface PostRepositoryInterface {
public function getAll();
public function find($id);
public function create(array $data);
}



2.MySQLPostRepository (Uygulama sınıfı)

<?php
//MySQLPostRepository
class MySQLPostRepository implements PostRepositoryInterface {
protected $pdo;

public function __construct(PDO $pdo) {
$this->pdo = $pdo;
}

public function getAll() {
$stmt = $this->pdo->query("SELECT * FROM posts");
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}

public function find($id) {
$stmt = $this->pdo->prepare("SELECT * FROM posts WHERE id = ?");
$stmt->execute([$id]);
return $stmt->fetch(PDO::FETCH_ASSOC);
}

public function create(array $data) {
$stmt = $this->pdo->prepare("INSERT INTO posts (title, content) VALUES (?, ?)");
return $stmt->execute([$data['title'], $data['content']]);
}
}



3.Controller (Kullanım)

<?php
//PostController
class PostController {
protected $postRepo;

public function __construct(PostRepositoryInterface $postRepo) {
$this->postRepo = $postRepo;
}

public function index() {
$posts = $this->postRepo->getAll();
foreach ($posts as $post) {
echo $post['title'] . "<br>";
}
}
}



4.Uygulama başlatma (manual dependency injection)


<?php
//index.php
$pdo = new PDO('mysql:host=localhost;dbname=testdb', 'root', '');
$postRepo = new MySQLPostRepository($pdo);
$controller = new PostController($postRepo);
$controller->index();


Gerçek Projelerde Kullanım Alanları

  • Laravel gibi frameworklerde Repository Pattern çok yaygındır.

  • Geniş ölçekli sistemlerde (e-ticaret, CRM, blog platformları)

  • Birden fazla veri kaynağının (MySQL, API, cache) kullanılacağı sistemlerde



Avantajları

  • Kod tekrarı azalır.

  • Daha test edilebilir hale gelir.

  • Kod mantıksal katmanlara ayrılır (Separation of Concerns).

  • Veritabanı değişiklikleri sistemin geneline yayılmaz.















Observer Pattern: Olaylara Tepki Veren Esnek Yapı


 

Observer Pattern Nedir?

Observer Pattern (Gözlemci Tasarım Deseni), bir nesnede olan değişikliği, bu nesneyi izleyen diğer nesnelere otomatik olarak bildiren bir yapıdır.


Basit Tanımıyla:

Bir nesne değiştiğinde, ona abone olan (gözlemleyen) tüm nesnelerin haberdar olmasını sağlar.

Ne İçin Kullanılır?

  • Bir olay gerçekleştiğinde birden fazla işlemin tetiklenmesi isteniyorsa

  • Kodun esnek ve modüler olması amaçlanıyorsa

  • İf-else zinciri kurmadan, farklı bileşenlerin bir olaya tepki vermesi gerekiyorsa


Gerçek Hayat Örnekleri:

  • Mail sistemi: Yeni kullanıcı kaydolunca hem e-posta gönder, hem log’a yaz, hem bildirim göster.

  • E-ticaret: Sipariş verildiğinde stok azalt, fatura oluştur, e-posta yolla.

  • Blog platformları: Yeni yazı eklendiğinde takipçilere bildirim gönder.



OCP ile Uyumu

Observer Pattern, Açık/Kapalı prensibini (OCP) uygular. Yeni dinleyiciler (observer) eklenebilir, ana kod değiştirilmez.


PHP ile Observer Pattern Uygulaması

(Observer Interface)


<?php
//Observer.php (Interface)
interface Observer {
public function update($data);
}



(Subject "Konu" Sınıfı)

<?php
//EventManager.php
class EventManager {
private $observers = [];

public function attach(Observer $observer) {
$this->observers[] = $observer;
}

public function notify($data) {
foreach ($this->observers as $observer) {
$observer->update($data);
}
}
}



(Observer Sınıfları)

<?php
//EmailSender.php
class EmailSender implements Observer {
public function update($data) {
echo "E-posta gönderildi: " . $data . "\n";
}
}

class Logger implements Observer {
public function update($data) {
echo "Log kaydedildi: " . $data . "\n";
}
}



(Kullanım)

<?php
//index.php
$event = new EventManager();

$email = new EmailSender();
$log = new Logger();

$event->attach($email);
$event->attach($log);

// Olay tetiklendi
$event->notify("Yeni kullanıcı kaydoldu!");




(Sonuc)

E-posta gönderildi: Yeni kullanıcı kaydoldu!
Log kaydedildi: Yeni kullanıcı kaydoldu!


Avantajları

  • Kod parçaları birbiriyle sıkı bağlı değildir (loosely coupled)

  • Yeni görevler kolayca eklenebilir

  • Birden fazla işlem bir olayla tetiklenebilir



Observer Pattern sayesinde sistemdeki bir değişiklikten haberdar olması gereken tüm yapılar bağımsız ve dinamik şekilde güncellenebilir. Bu sayede kodun sürdürülebilirliği ve esnekliği artar.





PHP Strategy Pattern ile Dinamik Algoritma Seçimi


 Kod yazarken bazen belirli bir işlemin birden fazla farklı şekilde yapılması gerekebilir. Mesela indirim hesaplama, sıralama, ödeme yöntemi gibi durumlarda tek bir yapıya sıkışmak istemeyiz. İşte bu gibi durumlarda Strategy Pattern hayat kurtarır.

Bu yazıda Strategy Pattern nedir, ne için kullanılır, hangi projelerde kullanılır ve PHP ile nasıl uygulanır adım adım öğreniyoruz.


Strategy Pattern Nedir?

Strategy Pattern, bir işlemi gerçekleştirmek için kullanılan algoritmanın (stratejinin) dinamik olarak değiştirilmesini sağlayan bir tasarım desenidir.

Yani:
➡️ Her iş için farklı bir strateji (sınıf) oluşturursun,
➡️ Bu stratejiler birbirinin yerine geçebilir olur,
➡️ Kullanım anında hangisini çalıştırmak istiyorsan onu seçersin.



Basit Bir Benzetme

Bir kahveci düşün. Müşteri ister Türk kahvesi ister espresso ister latte isteyebilir. Hepsi "kahve yap" işlemi gibi görünse de içerik farklıdır. Kahveci bunu esnek bir şekilde yönetmelidir. Strategy deseni burada sana bu esnekliği sağlar.


Strategy Pattern Ne İçin Kullanılır?

  • Bir işlemin birden fazla versiyonu varsa (farklı algoritmalar)

  • Uygulama çalışırken davranışı değiştirmek isteniyorsa

  • Kod tekrarını ve if-else karmaşasını azaltmak gerekiyorsa

  • Açık/kapalı prensibini (OCP) uygulamak istiyorsan


Kullanıldığı Gerçek Proje Türleri

Proje TürüKullanım Örneği
🛒 E-Ticaret SiteleriFarklı indirim stratejileri (yüzde, sabit, kampanya)
💳 Ödeme SistemleriFarklı ödeme yolları: kredi kartı, havale, kapıda
🔎 Sıralama UygulamalarıFarklı sıralama algoritmaları (A-Z, tarih, fiyat)
📦 Kargo SeçimiKargo türüne göre ücret hesaplama stratejileri


PHP ile Strategy Pattern Uygulaması

Senaryo: Bir e-ticaret uygulamasında sepet toplamına farklı indirim stratejileri uygulanacak.

(Interface)


<?php
//DiscountStrategy.php (Interface)
interface DiscountStrategy {
public function apply($amount);
}



(Yüzde indirimi)


<?php
//PercentageDiscount.php (Yüzde indirimi)
require_once 'DiscountStrategy.php';

class PercentageDiscount implements DiscountStrategy {
private $percentage;

public function __construct($percentage) {
$this->percentage = $percentage;
}

public function apply($amount) {
return $amount - ($amount * $this->percentage / 100);
}
}


(Sabit indirim)


<?php
//FixedDiscount.php (Sabit indirim)
require_once 'DiscountStrategy.php';

class FixedDiscount implements DiscountStrategy {
private $discountAmount;

public function __construct($discountAmount) {
$this->discountAmount = $discountAmount;
}

public function apply($amount) {
return max(0, $amount - $this->discountAmount);
}
}


(İndirimi uygulayan sınıf)


<?php
//Cart.php (İndirimi uygulayan sınıf)
class Cart {
private $amount;
private $strategy;

public function __construct($amount) {
$this->amount = $amount;
}

public function setDiscountStrategy(DiscountStrategy $strategy) {
$this->strategy = $strategy;
}

public function getTotal() {
if ($this->strategy) {
return $this->strategy->apply($this->amount);
}
return $this->amount;
}
}



(Kullanım)


<?php
//index.php (Kullanım)
require_once 'PercentageDiscount.php';
require_once 'FixedDiscount.php';
require_once 'Cart.php';

$cart = new Cart(200);

// Yüzde %20 indirim uygula
$cart->setDiscountStrategy(new PercentageDiscount(20));
echo "Yüzdeli indirimli toplam: " . $cart->getTotal() . "\n";

// Sabit 30 indirim uygula
$cart->setDiscountStrategy(new FixedDiscount(30));
echo "Sabit indirimli toplam: " . $cart->getTotal() . "\n";




(Sonuc)


Yüzdeli indirimli toplam: 160
Sabit indirimli toplam: 170


Neden Strategy Kullanmalıyız?

  • if/else ya da switch bloklarından kurtulursun

  • Yeni strateji eklemek için mevcut kodu değiştirmen gerekmez

  • Temiz, test edilebilir ve esnek bir yapı elde edersin








Factory Pattern ile Nesne Üretimi


 

Yazılım dünyasında nesne oluşturmak sıradan bir iş gibi görünse de, doğru yerde, doğru şekilde nesne üretmek birçok projede kritik öneme sahiptir. İşte bu noktada Factory Pattern (Fabrika Deseni) devreye girer.

Bu yazıda, Factory Pattern nedir, ne işe yarar, hangi projelerde kullanılır ve PHP ile nasıl uygulanır adım adım öğreniyoruz.


Factory Pattern Nedir? (Basit ama Detaylı Anlatım)

Factory Pattern, nesne oluşturma (instance creation) işlemini sınıfın dışına çıkartarak, nesne üretme işini özel bir “fabrika” sınıfa devreden bir tasarım desenidir.


Neden ihtiyaç duyulur?

Kod içinde sürekli olarak new kullanarak farklı sınıflardan nesneler oluşturmak, kod tekrarına ve sıkı bağımlılığa (tight coupling) yol açar.

Factory deseni bu problemi çözer:

  • Nesne üretimi tek bir noktadan yapılır.

  • Yeni sınıflar eklense bile, kodun geri kalanı etkilenmez.

  • Değişiklikler merkezi olarak yönetilir.


Basit bir benzetme:

Bir pizzacıda sipariş geldiğinde her pizzayı mutfaktaki çalışan kendisi üretirse kaos olur. Bunun yerine siparişi alan kişi pizzayı mutfaktaki üretim bölümüne (fabrikaya) iletir. Üretim bölümü pizzayı hazırlar ve sunar.


Factory Pattern Ne İçin Kullanılır?

  • Sınıflar arası bağımlılığı azaltmak için

  • Karmaşık nesne üretim mantığını tek yerde toplamak için

  • Kodun genişletilebilirliğini artırmak için




Factory Pattern Kullanılan Proje Türleri

Proje TürüKullanım Örneği
🛒 E-Ticaret SiteleriFarklı kargo firmalarına göre sınıf üretimi
📄 Belge YönetimiPDF, Word, Excel gibi farklı formatlar
💳 Ödeme SistemleriKredi kartı, havale, PayPal gibi yöntemler
🔌 API BağlantılarıFarklı servisler için ayrı client nesneleri


PHP ile Factory Pattern Örneği

Senaryo: Kullanıcı farklı araç türleri oluşturmak istiyor (Araba, Motosiklet). Her araç kendi çalıştırma metoduna sahip. Factory deseniyle bu nesneleri dinamik oluşturacağız.

1.)

Bu interface (arayüz), tüm araç sınıflarının (örneğin Car, Motorcycle) ortak bir davranışı (burada: start()) zorunlu olarak içermesini sağlar.

Her araç start() metodunu mutlaka yazmak zorundadır. Aksi halde hata alırsın.



<?php
//Vehicle.php
interface Vehicle {
public function start();
}


2.)


<?php
//Car.php
require_once 'Vehicle.php';

class Car implements Vehicle {
public function start() {
echo "Araba çalıştırıldı 🚗\n";
}
}


3.)

<?php
//Motorcycle.php
require_once 'Vehicle.php';

class Motorcycle implements Vehicle {
public function start() {
echo "Motosiklet çalıştırıldı 🏍️\n";
}
}



4.)

<?php
//VehicleFactory.php
require_once 'Car.php';
require_once 'Motorcycle.php';

class VehicleFactory {
public static function createVehicle($type) {
switch (strtolower($type)) {
case 'car':
return new Car();
case 'motorcycle':
return new Motorcycle();
default:
throw new Exception("Geçersiz araç türü.");
}
}
}




5.)

<?php
//index.php
require_once 'VehicleFactory.php';

try {
$vehicle1 = VehicleFactory::createVehicle('car');
$vehicle1->start(); // Araba çalıştırıldı

$vehicle2 = VehicleFactory::createVehicle('motorcycle');
$vehicle2->start(); // Motosiklet çalıştırıldı
} catch (Exception $e) {
echo $e->getMessage();
}




Avantajları

✅ Kod tekrarını azaltır
✅ Genişletilebilir bir yapı sunar
✅ Karmaşık nesne oluşturma işlemleri kontrol altına alınır
✅ Test yazmayı kolaylaştırır


Neden Factory Kullanmalıyız?

Factory Pattern sayesinde yazdığın kod daha esnek, test edilebilir ve sürdürülebilir hale gelir. Özellikle birden fazla türde nesne üretimi yapılan uygulamalarda bu desenin kullanılması profesyonel bir yaklaşımdır.