Durum Kalıbı
Coddy'nin PHP Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 79 / 91.
Durum Deseni (State Pattern), bir nesnenin iç durumu değiştiğinde davranışını değiştirmesine olanak tanıyan davranışsal bir tasarım desenidir. Farklı durumları yönetmek için karmaşık koşullu ifadeler kullanmak yerine, her durumu kendi sınıfında kapsüller ve davranışı mevcut durum nesnesine devredersiniz.
Bir otomat makinesini düşünün. Para bekliyor olmasına, ödemeyi almış olmasına veya bir ürün veriyor olmasına bağlı olarak farklı davranır.
Her durumun, hangi eylemlere izin verildiğine dair kendi kuralları vardır. Durum Deseni (State Pattern), her durum için bir sınıf oluşturarak bunu modeller.
<?php
interface OrderState {
public function proceed(Order $order): string;
public function getStatus(): string;
}
class PendingState implements OrderState {
public function proceed(Order $order): string {
$order->setState(new ProcessingState());
return "Order moved to processing";
}
public function getStatus(): string {
return "Pending";
}
}
class ProcessingState implements OrderState {
public function proceed(Order $order): string {
$order->setState(new ShippedState());
return "Order has been shipped";
}
public function getStatus(): string {
return "Processing";
}
}
class ShippedState implements OrderState {
public function proceed(Order $order): string {
return "Order already shipped";
}
public function getStatus(): string {
return "Shipped";
}
}
Context sınıfı, mevcut duruma bir referans tutar ve çağrıları ona devreder:
<?php
class Order {
private OrderState $state;
public function __construct() {
$this->state = new PendingState();
}
public function setState(OrderState $state): void {
$this->state = $state;
}
public function proceed(): string {
return $this->state->proceed($this);
}
public function getStatus(): string {
return $this->state->getStatus();
}
}
$order = new Order();
echo $order->getStatus() . "\n";
echo $order->proceed() . "\n";
echo $order->getStatus() . "\n";
echo $order->proceed() . "\n";
echo $order->getStatus();
Çıktı:
Pending
Order moved to processing
Processing
Order has been shipped
ShippedState Pattern, karmaşık switch ifadelerini ortadan kaldırır ve yeni durumlar eklemeyi kolaylaştırır. Her durum sınıfı, bir sonraki durumun hangisi olduğunu bilmekten sorumludur; bu da mantığı düzenli ve sürdürülebilir tutar.
Görev
KolayState Pattern kullanarak bir belge iş akışı sistemi oluşturalım. Bir içerik yönetim sistemindeki belgeler farklı aşamalardan geçer — taslak, inceleme ve yayınlanmış — ve her aşamanın hangi eylemlere izin verildiği ve belgeyi ilerletmeye çalıştığınızda ne olacağı konusunda kendi kuralları vardır.
Kodunuzu dört dosya halinde düzenleyeceksiniz:
DocumentState.php— Tüm belge durumları için sözleşmeyi belirleyen birDocumentStatearayüzü tanımlayın. İki yöntemi olmalıdır: belgeyi ilerletmeye çalışmak içinpublish(Document $document): stringve mevcut durum adını döndürmek içingetStatus(): string.States.php— DocumentState arayüzünü dahil edin ve onu uygulayan üç durum sınıfı oluşturun:DraftState—publish()çağrıldığında, belgeyiReviewStatedurumuna geçirir ve"Document sent for review"döndürür. Durumu"Draft"şeklindedir.ReviewState—publish()çağrıldığında, belgeyiPublishedStatedurumuna geçirir ve"Document published"döndürür. Durumu"Under Review"şeklindedir.PublishedState—publish()çağrıldığında, durum değiştirmeden"Document is already published"döndürür. Durumu"Published"şeklindedir.
Document.php— States dosyasını dahil edin ve bağlam (context) görevi gören birDocumentsınıfı oluşturun. Belgeniz şunları yapmalıdır:- Yapıcısında (constructor) bir başlık kabul etmeli ve
DraftStatedurumunda başlamalıdır - Mevcut durumu değiştirmek için bir
setState(DocumentState $state): voidyöntemine sahip olmalıdır - Mevcut durumun
publish()yöntemine delege eden birpublish(): stringyöntemine sahip olmalıdır - Mevcut durumun statüsünü döndüren bir
getStatus(): stringyöntemine sahip olmalıdır
- Yapıcısında (constructor) bir başlık kabul etmeli ve
main.php— Document dosyasını dahil edin. Bir girdi alacaksınız: belge üzerindepublish()yönteminin kaç kez çağrılacağı."My Article"başlığıyla birDocumentoluşturun. İlk olarak, başlangıç durumunu yazdırın. Ardından,publish()yöntemini belirtilen sayıda çağırın ve her çağrının sonucunu yeni bir satıra yazdırın. Son olarak, final durumunu yazdırın.Çıktı formatı:
Status: [initial status] [publish result 1] [publish result 2] ... Status: [final status]
Her durum sınıfı, iş akışında bir sonraki durumun hangisi olduğunu bilir, bu da geçiş mantığını düzenli ve değiştirilmesi kolay tutar. "Archived" gibi yeni bir durum eklemek, sadece yeni bir sınıf oluşturmak ve ilgili geçişleri güncellemek anlamına gelecektir.
Kopya kağıdı
Durum Deseni (State Pattern), her bir durumu kendi sınıfında kapsülleyerek, bir nesnenin iç durumu değiştiğinde davranışını değiştirmesine olanak tanıyan davranışsal bir tasarım desenidir.
Tüm durum sınıflarının uygulayacağı bir durum arayüzü tanımlayın:
<?php
interface OrderState {
public function proceed(Order $order): string;
public function getStatus(): string;
}Arayüzü uygulayan somut durum sınıfları oluşturun:
<?php
class PendingState implements OrderState {
public function proceed(Order $order): string {
$order->setState(new ProcessingState());
return "Order moved to processing";
}
public function getStatus(): string {
return "Pending";
}
}
class ProcessingState implements OrderState {
public function proceed(Order $order): string {
$order->setState(new ShippedState());
return "Order has been shipped";
}
public function getStatus(): string {
return "Processing";
}
}
class ShippedState implements OrderState {
public function proceed(Order $order): string {
return "Order already shipped";
}
public function getStatus(): string {
return "Shipped";
}
}Mevcut duruma bir referans tutan ve çağrıları ona devreden bir bağlam (context) sınıfı oluşturun:
<?php
class Order {
private OrderState $state;
public function __construct() {
$this->state = new PendingState();
}
public function setState(OrderState $state): void {
$this->state = $state;
}
public function proceed(): string {
return $this->state->proceed($this);
}
public function getStatus(): string {
return $this->state->getStatus();
}
}Kullanım örneği:
$order = new Order();
echo $order->getStatus() . "\n"; // Pending
echo $order->proceed() . "\n"; // Order moved to processing
echo $order->getStatus() . "\n"; // Processing
echo $order->proceed() . "\n"; // Order has been shipped
echo $order->getStatus(); // ShippedDurum Deseni, karmaşık switch ifadelerini ortadan kaldırır ve yeni durumlar eklemeyi kolaylaştırır. Her durum sınıfı, bir sonraki durumun hangisi olacağını bilmekten sorumludur.
Kendin dene
<?php
require_once 'Document.php';
// Girdiyi oku - publish() fonksiyonunun kaç kez çağrılacağı
$n = intval(trim(fgets(STDIN)));
// YAPILACAK: "My Article" başlıklı bir Document oluşturun
// YAPILACAK: Başlangıç durumunu şu formatta yazdırın: "Status: [status]"
// YAPILACAK: publish() fonksiyonunu n kez çağırın ve her sonucu yeni bir satıra yazdırın
// YAPILACAK: Son durumu şu formatta yazdırın: "Status: [status]"
?>Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Nesne Yönelimli Programlama bölümündeki tüm dersler
1OOP Temelleri
Harici DosyalarOOP'ye GirişSınıflar ve Nesneler$this Anahtar KelimesiMetotlarÖzelliklerYapıcı Metot (__construct)Yıkıcı Metot (__destruct)Özet - Basit Hesap Makinesi4Kalıtım
Temel Kalıtımparent:: Anahtar KelimesiMetot Geçersiz Kılmafinal Anahtar KelimesiSoyut SınıflarÖzet - Çalışan Hiyerarşisi7Kapsülleme
Public, Protected, PrivateErişim Belirleyicilere Derinlemesine BakışGetter ve Setter MetotlarıBilgi GizlemeConstructor Promotion (8.0)Özet - Öğrenci Kayıt Sistemi10İleri Düzey OOP Kavramları
Kompozisyon vs KalıtımDependency InjectionAnonim SınıflarEnum'lar (PHP 8.1)Fiber'lar (PHP 8.1)Nesne Klonlama: Derinlemesine İncelemeGenerator'lar ve Iterator'lar13Tasarım Kalıpları Bölüm 2
Komut KalıbıAdaptör KalıbıDekoratör KalıbıŞablon Metot KalıbıDurum KalıbıKompozit KalıbıRepository Kalıbı2İsim Alanları ve Autoloading
İsim Alanlarına Girişuse Anahtar KelimesiPSR-4 Autoloading StandartıComposer AutoloaderÖzet - Düzenli Proje5Arayüzler ve Sözleşmeler
Arayüzlere GirişArayüzleri UygulamaBirden Fazla Arayüz UygulamaArayüz vs Soyut SınıfArayüzler ile Tip BelirlemeÖzet - Şekil Hesaplayıcı8Sihirli Metotlar
Sihirli Metotlara Giriş__toString & __debugInfo__get, __set, __isset, __unset__call & __callStatic__clone & Nesne Klonlama__serialize & __unserializeÖzet - Özel Koleksiyon3Sınıf Özellikleri
Örnek ve Statik ÖzelliklerSınıflarda SabitlerStatik Metotlar ve ÖzelliklerPrivate ve Protected ÖzelliklerReadonly Özellikler (PHP 8.1)Özet - Banka Hesabı Yöneticisi6Çok Biçimlilik
Metot Geçersiz Kılmaya Yeniden BakışArayüzler ile Çok BiçimlilikType Hinting ve Union TypesLate Static BindingÖzet - Ödeme İşlemcisi9Trait'ler
Trait'lere GirişÇoklu Trait KullanımıTrait Çakışma ÇözümüTrait'lerde Soyut MetotlarTrait'ler ve Kalıtım12Tasarım Kalıpları Bölüm 1
Tasarım Kalıplarına GirişSingleton KalıbıFactory KalıbıObserver KalıbıStrategy Kalıbı15Final Meydan Okumaları
E-Öğrenme PlatformuBankacılık SistemiOyun Karakteri GeliştirmeAraç Kiralama Servisi