State tasarım deseni, bir nesnenin iç durumu değiştiğinde meydana gelecek değişimler sonrası çalışma zamanında dinamik olarak farklı davranışları sergileyebilmesini sağlayan bir tasarım desenidir.
State tasarım desenini biçimsel diller ve otomatalar, durum makinaları ile de ifade edilebilmektedir. Otomatalarda da olduğu gibi kodlarımızda da durumlar söz konusudur. Bir durumunda başka bir duruma gitmek, orada tekrar etmek ya da geriye dönmek gibi durumlarımız ve bu durumları gerçekleştirirken ki davranışlarımız mevcuttur.
Yazılım tarafından olaya baktığımızda aslında state diagramları ile ifade edilebilen her nesne için state deseninin uygulanabileceğini düşünebiliriz. Örneğin uygulamanın çalıştığı makinenin bellek durumları state kalıbına uygun olarak tasarlanabilir. Makinenin normal seviyede olması, sistem kaynaklarının çok tüketilmesi sonucu alarm haline geçmesi veya alarm verilmeden önce uyarı moduna geçmesi söz konusu olabilir. Bu durumlar arasındaki geçişler aslında bilgisayarın bazı iç değerlerine göre gerçeklenir. Memory, CPU, Running Process ölçümleri birer kriter olabilir ve örneğin Computer isimli bir nesnenin iç durumunu ifade edebilir.
Bu aşamada, bundan sonra internal state' i taşıyan yani davranışı değişecek olan nesneye Context dediğimizi düşünelim. Birden fazla davranış ve doğal olarak durum olabileceğinden, Context' in farklı durumlara erişebilip aralardaki geçişleri(Transitions) sağlayabilmesi gerekir. Bu durumda, Context tipinin tüm durumlar için ortak bir arayüz sunan başka bir tip ile (buna State diyebiliriz)Aggregation ilişkisini sağlaması uygundur.
State tipinin kendisi aslında, Context tipinin belli bir durumu ile ilişkilendirilmiş davranışların kapsüllenmesi için bir arayüz sunmaktadır. Bu arayüz sunumu aslı durum tipleri(Concrete State) tarafından değerlendirilebilir. Bu tanımlar doğrultusunda bu tasarım desenine ait UML diyagramı aşağıdaki gibi olacaktır.
State: Davranışın/olayın tanımlandığı arayüzdür, soyut sınıf da olabilmektedir.
ConcreteState:State arayüzünü uygular, bu sayede farklı durumlar meydana gelir.
Context: Durumu izlenecek olan nesnedir.
Senaryol olarak yiyecek otomatları düşünülebilir. Bu otomatlar için sıralı durumlar mevcuttur. Bunlar;
Ön hazırlıkların yapılması durumu => InitializeState
Bekleme durumu => WaitingState
Ürünün hazırlanması durumu => PreparingState
Ürünün teslim edilmesi durumu => DeliveryState
C# Kod Örneği:
// Davranışların tanımlandığı soyut sınıftır.// UML diyagramındaki State yapısına denk gelmektedir.publicabstractclassVendingMachineState{publicabstractvoidHandleState(VendingMachine context);}
// Farklı durumların meydana geldiği sınıf.// UML diyagramındaki State (VendingMachineState) yapısından türer.// UML diyagramındaki ConcreteState yapısına denk gelmektedir.classInitializeState:VendingMachineState{ // Başlangıç durumu ayarları yapıldıktan sonra WaitingState (hazır) durumuna geçer.publicoverridevoidHandleState(VendingMachine context) {Console.WriteLine("InitializeState: Ön hazırlıklar yapılıyor.");context.SetState(newWaitingState()); }}
// Farklı durumların meydana geldiği sınıf.// UML diyagramındaki State (VendingMachineState) yapısından türer.// UML diyagramındaki ConcreteState yapısına denk gelmektedir.classWaitingState:VendingMachineState{ // WaitingState durumunda herhangi bir yeni duruma geçmeye gerek yok. // Buradan sonraki durum gelen istek ile aksiyon alacaktır.publicoverridevoidHandleState(VendingMachine context) {Console.WriteLine("WaitingState: Otomata herhangi bir aksiyon bekliyor."); }}
// Farklı durumların meydana geldiği sınıf.// UML diyagramındaki State (VendingMachineState) yapısından türer.// UML diyagramındaki ConcreteState yapısına denk gelmektedir.classPreparingState:VendingMachineState{ // PreparingState durumunda ürün hazırlanması gibi işlemler yapılmaktadır. // Buradan sonraki durum ise ürünün verilmesi durumudur. (DeliveryState) publicoverridevoidHandleState(VendingMachine context) {Console.WriteLine("PreparingState: İstenilen ürün hazırlanıyor. Lütfen bekleyiniz");context.SetState(newDeliveryState()); }}
// Farklı durumların meydana geldiği sınıf.// UML diyagramındaki State (VendingMachineState) yapısından türer.// UML diyagramındaki ConcreteState yapısına denk gelmektedir.classDeliveryState:VendingMachineState{ // DeliveryState durumunda otomatadan ürünün teslim işlemleri yapılmaktadır. // Ürün verildikten sonra başlangıç, bekleme durumuna geçmektedir. (WaitingState)publicoverridevoidHandleState(VendingMachine context) {Console.WriteLine("DeliveryState: Ürün teslim ediliyor.");context.SetState(newWaitingState()); }}
// Durumu izlenecek olan sınıftır.// UML diyagramındaki Context yapısına denk gelmektedir.publicclassVendingMachine{privateVendingMachineState _state; // Otomata örneği oluştuğu zaman başlangıç durumuna geçiyor.publicVendingMachine() {SetState(newInitializeState()); }publicvoidSetState(VendingMachineState state) { _state = state;_state.HandleState(this); }publicvoidRequestProduct(string productName,double price) { // Burada ürünlere ait iş kodları olacaktır. // Ürün kontrolü, fiyatlandırma gibi kontroller. // Ürün ve fiyat olarak bir problemin olmadığı var sayılsın.SetState(newPreparingState()); }}
VendingMachine vendingMachine =newVendingMachine();vendingMachine.RequestProduct("COVID-19 MASKE",2);// output:// InitializeState: Ön hazırlıklar yapılıyor.// WaitingState: Otomata herhangi bir aksiyon bekliyor.// PreparingState: İstenilen ürün hazırlanıyor.Lütfen bekleyiniz// DeliveryState: Ürün teslim ediliyor.// WaitingState: Otomata herhangi bir aksiyon bekliyor.