State Design Pattern
State design patterni, nesnenin iç durumundaki değişikliklere göre çalışma zamanında farklı davranışlar sergilemesini sağlayan tasarım kalıbıdır. Yani biraz daha açarsak nesne belli özelliklerindeki değişimlere göre farklı davranışlar, fonksiyonellikler sergilemesi gibi düşünebiliriz.
Gündelik hayattan bir örnek ile devam edelim. Bir kredi kartınız olduğunu varsayalım ve bu kredi kartının durumlarına göre yani yazılım tarafından bakarsak iç özelliklerindeki değişimlere göre bankanız sizin hesabınızda değişiklikler yapıyor ve hesabınız farklı fonksiyonellikler sergiliyor.
– Kredi kartını yeni açtırdıysanız banka size standart bir tarife sunuyor (Standart faizler, standart kredi çekebilme limitleri vs).
– Kredi kartınızda çok fazla borç birikti ve ödeyemiyorsanız hesabı kara listeye çevirip size kredi vermiyor belki de faizlerinizi artırıyor.
– Eğer borçlarınızı düzenli ödüyorsanız da bir takım teşviklerin olduğu, rahatlıkla kredi alabildiğiniz bir premium hesaba çeviriyor.
Yani kredi kartınızın bakiye-borç değerindeki değişimlere göre bankanız dinamik olarak sizin hesabınızı farklı davranışlara yani durumlara(state’lere) sokabiliyor.
İşte state design patterni de tam olarak bunu yapıyor. Kredi kartı nesnenizin, iç özellikleri değişiyor ve farklı davranışlar sergiliyor. Bu yapıyı normal şartlarda if else koşul yapılarıyla kurabiliyor olsak da, state pattern ile tanımlanan her state eski yapıyı değiştirmeden sisteme direkt tak çıkar yani open closure principle’a uygun bir şekilde entegre olabilir.
Farklı statelerde farklı fonksiyonellikler sergileyen nesne.
Olayı yazılım diline dökersek, Aşağıdaki UML diagramı state patternin uml diagramıdır.
UML diagramındaki aktörlerimize , context classı değişik statelerde farklı fonksiyonellik sergileyecek olan nesnemizdir. Bu sebeple state değişimlerini context classı takip eder ve yönetir. Yukarıdaki banka örneğinde bu kredi kartı ve borç bakiye bilgilerine karşılık gelir.
Context tipinin tüm stateler için ortak bir arayüz sunan başka bir tip ile ilişki kurması gerekir ki bu da soyut State classıdır. State classı değişik durumları temsil eden ortak arayüzdür. Bu arayüz sunumu aslı durum tipleri(Concrete State) tarafından değerlendirilebilir. Concerete Stateler de (StateOne, StateTwo, StateThree) farklı durumları temsil eder. Kredi kartı örneği için bu normal üyelik, kara liste, premium üyelik olarak düşünülebilir.
Aşağıda bir banka hesabının state değişimlerine göre normal hesap ve altın hesabı olarak hareket etmesi state design patterni ile sağlanmıştır.
//Soyut State nesnesi public interface IAccountState { void WithdrawMoney(); void PayInterest(); } //Concrete State nesnesi - 1 public class GoldAccount : IAccountState { public void PayInterest() { Console.WriteLine("Interest paid with Golden Account"); } public void WithdrawMoney() { Console.WriteLine("Money is taken with Golden Account"); } } //Concrete State nesnesi - 2 public class NormalAccount : IAccountState { public void PayInterest() { Console.WriteLine("Interest paid with Normal Account"); } public void WithdrawMoney() { Console.WriteLine("Money is taken with Normal Account"); } } //State değişimlerini yöneten ve statelere göre davranışları değişen context nesnesi public class Account { private IAccountState _accountState; public Account() { _accountState = new NormalAccount(); } public void PayInterest() { _accountState.PayInterest(); } public void WithdrawMoney() { _accountState.WithdrawMoney(); } public void ChangeStatus(IAccountState newACcountState) { _accountState = newACcountState; } } static void Main(string[] args) { Account account = new Account(); account.WithdrawMoney(); account.PayInterest(); account.ChangeStatus(new GoldAccount()); account.WithdrawMoney(); account.PayInterest(); Console.ReadKey(); }