Durum Kalıbı
Coddy'nin PHP Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 79 / 91.
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ı işlemek 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 düşün. Para bekliyor, has ödeme almış ya da bir ürün dağıtıyor olmasına bağlı olarak farklı davranır.
Her durumun hangi eylemlere izin verildiğine ilişkin kendi kuralları vardır. 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";
}
}
Bağlam 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, kapsamlı switch ifadelerini ortadan kaldırır ve yeni durumlar eklemeyi kolaylaştırır. Her durum sınıfı, kendisinden sonra hangi durumun geleceğini bilmekten sorumludur; bu sayede mantık düzenli ve sürdürülebilir kalır.
Görev
KolayState Pattern'ı kullanarak bir belge iş akışı sistemi oluşturalım. Bir içerik yönetim sistemindeki belgeler, taslak, inceleme ve yayımlanmış gibi farklı aşamalardan geçer; 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 dosyaya ayıracaksınız:
DocumentState.php: Tüm belge durumları için sözleşmeyi belirleyen birDocumentStatearayüzü tanımlayın. İki yöntemi olmalıdır: belgeyi ilerletmeyi denemek içinpublish(Document $document): stringve mevcut durum adını döndürmek içingetStatus(): string.States.php: DocumentState arayüzünü dahil edin ve bunu 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 durumu değiştirmeden"Document is already published"döndürür. Durumu"Published"şeklindedir.
Document.php: States dosyasını dahil edin ve bağlam görevi gören birDocumentsınıfı oluşturun. Belgeniz:- Yapıcısında bir başlık kabul etmeli ve
DraftStatedurumunda başlamalıdır - Mevcut durumu değiştirmek için
setState(DocumentState $state): voidyöntemine sahip olmalıdır - Mevcut durumun
publish(): stringyöntemine delege eden birpublish()yöntemine sahip olmalıdır - Mevcut durumun durumunu döndüren bir
getStatus(): stringyöntemine sahip olmalıdır
- Yapıcısında 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ğı.Başlığı
Documentolan bir"My Article"oluşturun. Önce başlangıç durumunu yazdırın. Ardındanpublish()yöntemini belirtilen sayıda çağırın ve her çağrının sonucunu yeni bir satırda yazdırın. Son olarak, son durumu yazdırın.Çıktı biçimi:
Status: [initial status] [publish result 1] [publish result 2] ... Status: [final status]
Her durum sınıfı, iş akışında hangi durumun sırada olduğunu bilir; böylece geçiş mantığı düzenli ve kolayca değiştirilebilir kalır. "Archived" gibi yeni bir durum eklemek, yalnızca yeni bir sınıf oluşturmak ve ilgili geçişleri güncellemek anlamına gelir.
Kendin dene
<?php
require_once 'Document.php';
// Girdiyi oku - publish() çağırma sayısı
$n = intval(trim(fgets(STDIN)));
// TODO: "My Article" başlıklı bir Document oluştur
// TODO: Başlangıç durumunu şu formatta yazdır: "Status: [status]"
// TODO: publish() metodunu n kez çağır, her sonucu yeni bir satıra yazdır
// TODO: Son durumu şu formatta yazdır: "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 SözcüğüMetotlarÖzelliklerYapıcı (__construct)Yıkıcı (__destruct)Tekrar - Basit Hesap Makinesi4Kalıtım
Temel Kalıtımparent:: Anahtar SözcüğüMetot Geçersiz Kılmafinal Anahtar SözcüğüSoyut SınıflarTekrar - Çalışan Hiyerarşisi7Kapsülleme
Public, Protected, PrivateErişim Belirleyicileri DerinlemesineGetter ve Setter'larBilgi GizlemeYapıcı Özellik Terfisi (8.0)Tekrar - Öğrenci Kayıt Sistemi10İleri Düzey OOP Kavramları
Composition ve KalıtımBağımlılık EnjeksiyonuAnonim SınıflarEnum'lar (PHP 8.1)Fiber'lar (PHP 8.1)Nesne Klonlamaya Derinlemesine BakışÜreteçler ve Yineleyiciler13Tasarı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ıBileşik KalıpDepo Kalıbı2Namespace’ler ve Autoloading
Namespace’lere Girişuse Anahtar SözcüğüPSR-4 Autoloading StandardıComposer AutoloaderTekrar - Düzenli Proje5Arayüzler ve Sözleşmeler
Arayüzlere GirişArayüzleri UygulamaBirden Çok Arayüz UygulamaArayüz ve Soyut Sınıf KarşılaştırmasıArayüzlerle Tür İpuçlarıTekrar - Şekil Hesaplayıcı8Sihirli Metotlar
Sihirli Metotlara Giriş__toString ve __debugInfo__get, __set, __isset, __unset__call ve __callStatic__clone ve Nesne Klonlama__serialize ve __unserializeTekrar - Özel Koleksiyon3Sınıf Özellikleri
Örnek ve Statik ÖzelliklerSınıflarda SabitlerStatik Metotlar ve ÖzelliklerPrivate ve Protected ÖzelliklerSalt Okunur Özellikler (PHP 8.1)Tekrar - Banka Hesabı Yöneticisi6Çok Biçimlilik
Metot Geçersiz Kılmayı Yeniden Ele AlmaArayüzler Yoluyla Çok BiçimlilikTür İpuçları ve Birleşim TürleriGeç Bağlanan Statik ÇağrılarÖzet - Ödeme İşlemcisi9Trait'ler
Trait'lere GirişBirden Çok Trait KullanımıTrait Çakışmalarını ÇözümlemeTrait'lerde Soyut MetotlarTrait'ler ve Kalıtım Karşılaştırması12Tasarım Desenleri 1. Bölüm
Tasarım Desenlerine GirişSingleton DeseniFactory DeseniObserver DeseniStrategy DeseniKendi başına pratik yap: Online PHP derleyicisi