Sitemap

State Design Pattern

3 min readJan 31, 2026

--

Bir Backend Developer olarak kariyerinizin bir noktasında, binlerce satıra ulaşmış, içinde kaybolduğunuz o devasa if-else veya switch-case bloklarıyla mutlaka karşılaşmışsınızdır. Özellikle bir siparişin durumu, bir ödemenin akıbeti veya bir oyun karakterinin hareketleri söz konusu olduğunda, kodun yönetilebilirliği hızla azalır.

Bugün, nesne yönelimli programlamanın (OOP) en zarif çözümlerinden biri olan State Design Pattern’ı, kavramsal derinliğiyle ve gerçek dünya senaryolarıyla inceleyeceğiz. Üstelik sıkça karıştırıldığı Strategy Pattern ile arasındaki o ince çizgiyi de netleştireceğiz.

Sorun: “If-Else” Cehennemi (Cyclomatic Complexity)

Bir Fintech projesi geliştirdiğinizi hayal edin (Adına Orion diyelim). Bir kredi başvurusu sürecini yönetiyorsunuz. Başvuru şu durumlardan geçiyor: Taslak -> İncelemede -> Onaylandı -> Kullandırıldı.

Geleneksel (ve kötü) yöntemle kod muhtemelen şöyle görünecektir:

public void onayla() {
if (durum.equals("TASLAK")) {
throw new RuntimeException("Taslak doğrudan onaylanamaz, önce incelemeye gönder!");
} else if (durum.equals("INCELEMEDE")) {
this.durum = "ONAYLANDI";

} else if (durum.equals("ONAYLANDI")) {
throw new RuntimeException("Zaten onaylanmış!");
} else if (durum.equals("REDDEDILDI")) {
...
}
}

Bu kodun sorunu nedir?

  1. Gelişime Kapalı: Yeni bir durum eklendiğinde (örneğin “Ek Belge İsteniyor”), tüm metodları tek tek gezip o else-if bloğunu eklemeniz gerekir. (Open/Closed Principle ihlali).
  2. Okunabilirlik: İş mantığı, durum kontrolleri arasına gömülmüştür.

Çözüm: State Design Pattern.

Çözüm: State Pattern Nedir?

State Pattern, bir nesnenin iç durumu değiştiğinde davranışının da değişmesini sağlayan bir tasarım desenidir. Sanki nesne, sınıfını değiştirmiş gibi davranır.

Felsefesi şudur: “Durumu kontrol etme (if), durumu bir sınıfa dönüştür ve işi ona devret.”

Mimari Bileşenler

  1. Context (Bağlam): İstemcinin (Client) muhatap olduğu ana sınıftır. Şu anki durumu (State) içinde barındırır.
  2. State (Arayüz): Tüm durumların uygulaması gereken ortak davranışları tanımlar.
  3. Concrete States (Somut Durumlar): Her bir durumun kendi mantığını ve bir sonraki duruma geçiş kurallarını içerdiği sınıflardır.

Uygulama: Kredi Başvuru Sistemi (Java)

Gelin Orion projemizdeki kredi başvuru sürecini bu desenle kodlayalım.

1. State Arayüzü

Önce kredi başvurusunun yapabileceği eylemleri tanımlayalım.

public interface LoanState {
void submitReview();
void approve();
void reject();
void disburse();
}

2. Context (Kredi Başvurusu)

Bu sınıf, durumu tutar ve dış dünyadan gelen istekleri o anki duruma yönlendirir (Delegation).

public class LoanApplication {
private LoanState state;

public LoanApplication() {

this.state = new DraftState(this);
}


public void changeState(LoanState newState) {
this.state = newState;
}


public void submitReview() { state.submitReview(); }
public void approve() { state.approve(); }
public void disburse() { state.disburse(); }
}

3. Somut Durumlar (Concrete States)

İşte büyünün gerçekleştiği yer. Her sınıf kendi kurallarını ve bir sonraki adımı bilir.

Get Muratguven’s stories in your inbox

Join Medium for free to get updates from this writer.

Durum 1: Taslak (Draft)

public class DraftState implements LoanState {
private LoanApplication app;

public DraftState(LoanApplication app) { this.app = app; }

@Override
public void submitReview() {
System.out.println("Başvuru incelemeye gönderildi.");

app.changeState(new UnderReviewState(app));
}

@Override
public void approve() {
System.out.println("HATA: Taslak halindeki başvuru onaylanamaz.");
}


}

Durum 2: İncelemede (UnderReview)

public class UnderReviewState implements LoanState {
private LoanApplication app;

public UnderReviewState(LoanApplication app) { this.app = app; }

@Override
public void approve() {
System.out.println("Kredi onaylandı! Sözleşme bekleniyor.");
app.changeState(new ApprovedState(app));
}

@Override
public void reject() {
System.out.println("Kredi reddedildi.");
app.changeState(new RejectedState(app));
}

@Override
public void submitReview() {
System.out.println("Zaten incelemede.");
}

}

Kritik Soru: Strategy Pattern ile Farkı Ne?

UML diyagramlarına baktığınızda State ve Strategy neredeyse ikiz kardeş gibidir. İkisi de bir Interface, Concrete sınıflar ve bir Context kullanır. Ancak niyetleri (Intent) ve çalışma şekilleri tamamen farklıdır.

1. Kontrol Kimde?

  • Strategy Pattern: Kontrol Client’tadır (Kodu çağıran kişi). “Bana en hızlı rotayı çiz” veya “Ödemeyi Kredi Kartı ile yap” diyerek stratejiyi dışarıdan sen seçersin. Stratejiler birbirinden habersizdir.
  • State Pattern: Kontrol State nesnelerinin kendisindedir. “Su kaynadı” olayından sonra “Buharlaşma” durumuna geçişi kodun akışı belirler. Dışarıdan “Hadi şimdi buharlaş” demezsiniz, süreç oraya akar.

2. “Menü” vs. “Domino Taşları”

  • Strategy bir Restoran Menüsüdür: Pizza veya Hamburger seçebilirsiniz. Pizza yemeniz, otomatik olarak Hamburger siparişi vermenizi tetiklemez. Birbirlerinden bağımsızdırlar.
  • State bir Domino Dizilimidir: Bir taş devrildiğinde (State A tamamlandığında), fiziksel olarak bir sonraki taşa çarpar (State B’yi new’ler ve Context’e atar). Durumlar birbirini tanır ve tetikler.

Ne Zaman Kullanmalıyım?

Aşağıdaki durumlardan en az ikisi varsa, State Pattern kullanma vakti gelmiştir:

  1. [ ] Bir nesnenin davranışı, o anki durumuna (status) göre radikal şekilde değişiyorsa.
  2. [ ] Kodunuzda status değerini kontrol eden devasa switch-case veya if-else blokları varsa.
  3. [ ] Durum geçişleri (Transitions) karmaşık kurallara sahipse (Örn: A'dan sadece B'ye geçilebilir, C'ye geçilemez).

İleri Seviye: Spring State Machine

Projeniz büyüdükçe (örneğin Orion projesinde binlerce siparişi yönetirken), manuel State sınıfları yazmak yerine Spring State Machine gibi hazır framework’ler kullanmak daha mantıklıdır. Bu kütüphaneler şunları sağlar:

  • Durumların veritabanında saklanması (Persistence).
  • Karmaşık geçiş kuralları (Guards).
  • Event-Driven mimari ile entegrasyon.

Sonuç

State Pattern, karmaşık iş akışlarını yönetilebilir, test edilebilir ve genişletilebilir küçük parçalara böler. İlk başta “çok fazla sınıf oluşturuyoruz” gibi görünse de, projenin 6. ayında yeni bir iş kuralı eklendiğinde, sadece tek bir sınıfı değiştirerek işi hallettiğinizde kendinize teşekkür edeceksiniz.

--

--