Durum Tasarım Kalıbı (State Design Pattern)

Eyl 08, 2013

Durum tasarım kalıbı davranışsal tasarım kalıplarının alt dallarından biri olarak kabul edilir. Bir nesnenin durumu değiştiğinde, davranışı da değişirse, diğer bir ifadeyle nesneler farklı durumlarda farklı davranışlar gösterirse, durum tasarım kalıbı kullanılabilir. Kullanıcı açısından, nesne sınıfını değiştiriyormuş izlenimi verir. Uygulamanın gerektirdiği doğrultuda yeni davranışlar eklenip çıkarılmasına olanak sağlar.

Durum (State) tasarım kalıbının kullanılması, nesnelerin durumlarına bağlı değişen davranışlarının karmaşık koşul ve kontrol (if/else, switch) ifadeleriyle yönetilmesini önler.

Durum tasarım kalıbının UML diyagramı aşağıdaki şekildedir.


 

 

 

 

 

 

Bileşenler:

Bu kalıpta yer alan nesneler ve sınıflar;

Bağlam (Context)

  • İstemcilerle ilişkili  Arayüzü (Interface) tanımlar.
  • Anlık durumu tanımlayan  Somut Durum (ConcreteState) alt sınıfının nesnesini korur.

Durum (State)

  • Bağlam (Context) ın özel durumuyla ilgili bir davranışı, kısa ve öz biçimde açıklamak için arayüz tanımlar.

 Somut Durum (Concrete State)

  • Her alt sınıf Bağlam (Context) sınıfının durumuyla ilişkili bir davranışı uygular.

Durum Tasarım Kalıbı İle İlgili Uygulama

Hazırlanan örnek uygulamada içerik sınıfı olarak Hesap sınıfı oluşturulur ve sınıf içinde hesaba ait bakiye, hesabın durumu gibi değişkenler belirtilerek hesapla ilgili yapılan işlemlerin metodları belirlenir. Soyut olarak oluşturulan Durum sınıfında hesabın durumu ile ilgili ayrıntılı işlemlerin yapılabilmesi için soyut HesabaYatir, HesaptanCek ve FaizIslemi metodları belirtilir. AltinDurum, KirmiziDurum, GumusDurum sınıfları ise Durum sınıfından türetilmiş olup DurumDeğisimiKontrolu metoduyla hesabın anlık bakiye durumunun hangi durumda olduğuna karar verilir. Yazılan uygulamanın giriş kısmındaki Main metodunda da Hesap sınıfından oluşturulan hesap nesnesi üzerinde çeşitli finansal işlemler uygulanarak ekran çıktısı olarak hesabın bakiyesi ve durumu ile ilgili bilgiler gösterilir.

using System;
namespace DurumKalibi
{
    class MainApp
    {
        static void Main()
        {
            Hesap hesap = new Hesap("Kullanıcı Adı");
            Console.WriteLine("Hesap Sahibi  :" + "Kullanıcı Adı"); 

            hesap.HesabaYatir(500.0);
            hesap.HesabaYatir(300.0);
            hesap.HesabaYatir(550.0);
            hesap.FaizIslemi();
            hesap.HesaptanCek(2000.00);
            hesap.HesaptanCek(1100.00); 

            Console.ReadKey();
        }
    }
        abstract class Durum
    {

        protected Hesap hesap;
        protected double bakiye;
        protected double faiz;
        protected double altLimit;
        protected double ustLimit;
        public Hesap Hesap

        {
            get { return hesap; }
            set { hesap = value; }
        }

        public double Bakiye

        {
            get { return bakiye; }
            set { bakiye = value; }
        }

        public abstract void HesabaYatir(double miktar);
        public abstract void HesaptanCek(double miktar);
        public abstract void FaizIslemi();
   }

    class KirmiziDurum : Durum

    {
        private double _servisUcreti;
        public KirmiziDurum(Durum durum)

        {
            this.bakiye = durum.Bakiye;
            this.hesap = durum.Hesap;
            VeriGirisi();
        }

        private void VeriGirisi()

        {
            faiz = 0.0;
            altLimit = -100.0;
            ustLimit = 0.0;
            _servisUcreti = 15.00;
        }

        public override void HesabaYatir(double miktar)

        {
            bakiye += miktar;
            DurumDegisimiKontrolu();
        }

        public override void HesaptanCek(double miktar)

        {
            miktar = miktar - _servisUcreti;
            Console.WriteLine("Para çekmek için yeterli kaynak mevcut değildir.");
        }

        public override void FaizIslemi()

        {
        }

        private void DurumDegisimiKontrolu()

        {
            if (bakiye > ustLimit)
            {
                hesap.Durum = new GumusDurum(this);
            }
        }
    }

    class GumusDurum : Durum

    {
        public GumusDurum(Durum durum) :
        this(durum.Bakiye, durum.Hesap)
        {
        }

        public GumusDurum(double bakiye, Hesap hesap)

        {
            this.bakiye = bakiye;
            this.hesap = hesap;
            VeriGirisi();
        }

        private void VeriGirisi()

       {
            faiz = 0.0;
            altLimit = 0.0;
            ustLimit = 1000.0;
        }

        public override void HesabaYatir(double miktar)

        {
            bakiye += miktar;
            DurumDegisimiKontrolu();
        }

        public override void HesaptanCek(double miktar)

        {
            bakiye -= miktar;
            DurumDegisimiKontrolu();
        }

        public override void FaizIslemi()

        {
            bakiye += faiz * bakiye;
            DurumDegisimiKontrolu();
        }

        private void DurumDegisimiKontrolu()

        {
            if (bakiye < altLimit)
            {
                hesap.Durum = new KirmiziDurum(this);
            }
            else if (bakiye > ustLimit)
            {
                hesap.Durum = new AltinDurum(this);
            }
        }
    }

    class AltinDurum : Durum

    {
        public AltinDurum(Durum durum)
              : this(durum.Bakiye, durum.Hesap)
        {
        }

         public AltinDurum(double bakiye, Hesap miktar)

        {
            this.bakiye = bakiye;
            this.hesap = miktar;
            VeriGirisi();
        }

        private void VeriGirisi()

        {
            faiz = 0.05;
            altLimit = 1000.0;
            ustLimit = 10000000.0;
        }

        public override void HesabaYatir(double miktar)

        {
            bakiye += miktar;
            DurumDegisimiKontrolu();
        }

        public override void HesaptanCek(double miktar)

        {
            bakiye -= miktar;
            DurumDegisimiKontrolu();
        }

         public override void FaizIslemi()

        {
            bakiye += faiz * bakiye;
            DurumDegisimiKontrolu();
        }  

          private void DurumDegisimiKontrolu()

        {
            if (bakiye < 0.0)
            {
                hesap.Durum = new KirmiziDurum(this);
            }

            else if (bakiye < altLimit)
            {
                hesap.Durum = new GumusDurum(this);
            }
        }
    }

   class Hesap

    {
        private Durum _durum;
        private string _hesapSahibi;
        public Hesap(string hesapSahibi)

        {
            this._hesapSahibi = hesapSahibi;
            this._durum = new GumusDurum(0.0, this);
        }       

        public double Bakiye

        {
            get { return _durum.Bakiye; }
        }

        public Durum Durum

        {
            get { return _durum; }
            set { _durum = value; }
        }

        public void HesabaYatir(double miktar)

        {
            _durum.HesabaYatir(miktar);
            Console.WriteLine("Hesaba Yatırılan {0:C} --- ", miktar);
            Console.WriteLine(" Bakiye = {0:C}", this.Bakiye);
            Console.WriteLine(" Hesap Durumu = {0}", this.Durum.GetType().Name);
            Console.WriteLine("");
        }

        public void HesaptanCek(double miktar)

        {
            _durum.HesaptanCek(miktar);
            Console.WriteLine("Hesaptan Çekilen {0:C} --- ", miktar);
            Console.WriteLine(" Bakiye = {0:C}", this.Bakiye);
            Console.WriteLine(" Hesap Durumu = {0}\n", this.Durum.GetType().Name);
        }

        public void FaizIslemi()

        {
            _durum.FaizIslemi();
            Console.WriteLine("Ödenen Faiz --- ");
            Console.WriteLine(" Bakiye = {0:C}", this.Bakiye);
            Console.WriteLine(" Hesap Durumu = {0}\n", this.Durum.GetType().Name);
        }
    }
}

Bu uygulamanın ekran çıktısı aşağıda bulunmaktadır.