Derinlemesine yazılım eğitimleri için kanalımı takip edebilirsiniz...

C# State Design Pattern(State Tasarım Deseni)

    class Program
    {
        static void Main(string[] args)
        {
            ATMMachine atm = new ATMMachine();
            #region ATM'ye kart takıp geri çıkarma
            atm.InsertCard();
            atm.EjectCard();
            Console.WriteLine("*********");
            #endregion
            #region Doğrulanmış pin ile para çekme ve üzerine tekrar para çekme talebinde bulunma
            atm.InsertCard();
            atm.InsertPin(123);
            atm.RequestCash(1500);
            atm.RequestCash(100);
            Console.WriteLine("*********");
            //ATM'de kalan bakiye 500
            #endregion
            #region Para çekme
            atm.InsertCard();
            atm.InsertPin(123);
            atm.RequestCash(100);
            Console.WriteLine("*********");
            //ATM'de kalan bakiye 400
            #endregion
            #region Para çekme
            atm.InsertCard();
            atm.InsertPin(123);
            atm.RequestCash(300);
            Console.WriteLine("*********");
            //ATM'de kalan bakiye 100
            #endregion
            #region Para çekme
            atm.InsertCard();
            atm.InsertPin(123);
            atm.RequestCash(100);
            Console.WriteLine("*********");
            //ATM'de kalan bakiye 0
            #endregion
            #region Para olmayan ATM'den para çekme talebi
            atm.InsertCard();
            atm.InsertPin(123);
            atm.RequestCash(100);
            Console.WriteLine("*********");
            //Tüm işlemlerde para yok uyarısı!
            #endregion
        }
    }

    abstract class ATMState
    {
        public abstract void InsertCard();
        public abstract void EjectCard();
        public abstract void InsertPin(int pin);
        public abstract void RequestCash(int cashToWithdraw);
    }

    class ATMMachine
    {
        ATMState noCard;
        ATMState hasCard;
        ATMState hasPin;
        ATMState noCash;

        ATMState state;
        public ATMMachine()
        {
            noCard = new NoCard(this);
            hasCard = new HasCard(this);
            hasPin = new HasPin(this);
            noCash = new NoCash(this);
            state = noCard;
        }
        public ATMState State { set => state = value; }

        public void SetNoCard()
            => state = noCard;
        public void SetHasCard()
            => state = hasCard;
        public void SetHasPin()
            => state = hasPin;
        public void SetNoCash()
            => state = noCash;

        public int CashInMachine { get; set; } = 2000;
        public bool CorrectPinEntered { get; set; } = false;
        public void InsertCard()
            => state.InsertCard();
        public void EjectCard()
            => state.EjectCard();
        public void InsertPin(int pin)
            => state.InsertPin(pin);
        public void RequestCash(int cashToWithdraw)
            => state.RequestCash(cashToWithdraw);
    }

    class NoCard : ATMState
    {
        ATMMachine _context;
        public NoCard(ATMMachine context)
            => _context = context;

        public override void EjectCard()
            => Console.WriteLine("Lütfen önce kartı takınız.");
        public override void InsertCard()
        {
            Console.WriteLine("Lütfen pin giriniz.");
            _context.SetHasCard();
        }
        public override void InsertPin(int pin)
            => Console.WriteLine("Lütfen önce kartı takınız.");
        public override void RequestCash(int cashToWithdraw)
            => Console.WriteLine("Lütfen önce kartı takınız.");
    }

    class HasCard : ATMState
    {
        ATMMachine _context;
        public HasCard(ATMMachine context)
            => _context = context;

        public override void EjectCard()
        {
            Console.WriteLine("Kart çıkarılmıştır.");
            _context.SetNoCard();
        }
        public override void InsertCard()
            => Console.WriteLine("Aynı anda birden fazla kart takamazsınız!");
        public override void InsertPin(int pin)
        {
            if (pin == 123)
            {
                Console.WriteLine("Pin doğrulandı!");
                _context.CorrectPinEntered = true;
                _context.SetHasPin();
            }
            else
            {
                Console.WriteLine("Geçersiz pin girildi!");
                _context.CorrectPinEntered = false;
                Console.WriteLine("Kart çıkarılmıştır.");
                _context.SetNoCard();
            }
        }
        public override void RequestCash(int cashToWithdraw)
            => Console.WriteLine("Lütfen önce pini giriniz.");
    }

    class HasPin : ATMState
    {
        ATMMachine _context;
        public HasPin(ATMMachine context)
            => _context = context;

        public override void EjectCard()
        {
            Console.WriteLine("Kart çıkarılmıştır.");
            _context.SetNoCard();
        }
        public override void InsertCard()
            => Console.WriteLine("Aynı anda birden fazla kart takamazsınız!");
        public override void InsertPin(int pin)
            => Console.WriteLine("Doğrulanmış bir pin zaten girilmiştir.");
        public override void RequestCash(int cashToWithdraw)
        {
            if (cashToWithdraw > _context.CashInMachine)
            {
                Console.WriteLine("Çekmek istenen tutar adil bedeli aşmaktadır.");
                Console.WriteLine("Kart çıkarılmıştır.");
                _context.SetNoCard();
            }
            else
            {
                Console.WriteLine($"{cashToWithdraw} tutarında para çekilmiştir.");
                _context.CashInMachine -= cashToWithdraw; //ATM'de ki para güncelleniyor.
                Console.WriteLine("Kart çıkarılmıştır.");
                _context.SetNoCard();
                Console.WriteLine($"ATM'de kalan para : {_context.CashInMachine}");

                if (_context.CashInMachine <= 0)
                    _context.SetNoCash();
            }
        }
    }

    class NoCash : ATMState
    {
        ATMMachine _context;
        public NoCash(ATMMachine context)
            => _context = context;

        public override void EjectCard()
         => Console.WriteLine("Para yok para :)");
        public override void InsertCard()
            => Console.WriteLine("Para yok para :)");
        public override void InsertPin(int pinEntered)
            => Console.WriteLine("Para yok para :)");
        public override void RequestCash(int cashToWithdraw)
            => Console.WriteLine("Para yok para :)");
    }

Yukarıda bir önceki sayfadaki 1. senaryonun konusu olan ATM senaryosunun farklı bir varyasyonu örneklendirilmiştir. Burada önceki tasarımla arada iki temel fark mevcuttur. Bu farklardan birincisi, her durum değişiminde yeni bir Concrete State nesnesi oluşturmaktansa bu nesneleri tek seferliğine Context sınıfında oluşturuyoruz ve ilgili sınıfın constructor’ın da instance’larını tanımlıyoruz.
C# State Design Pattern(State Tasarım Deseni)
Durum değişimlerini Context‘te üretilen Concrete State nesneleri üzerinden sağlayabilmek için Context içerisinde her bir duruma özel set metotları oluşturuyoruz.
C# State Design Pattern(State Tasarım Deseni)
Ve Concrete State nesnelerinde bu metotlar aracılığıyla durum değişimini gerçekleştiriyoruz.
C# State Design Pattern(State Tasarım Deseni)
İkinci fark ise, State‘te ki metotlar Context nesnesini parametre olarak almamakta,

Önceki Sonraki
C# State Design Pattern(State Tasarım Deseni) C# State Design Pattern(State Tasarım Deseni)

ilgili nesneyi Concrete State nesnelerine Context sınıfında üretilirken constructor’ları üzerinden verilmektedir.
C# State Design Pattern(State Tasarım Deseni)
Böylece her bir metotta yoğun parametre tanımı olmaksızın tek bir tanım ve kullanım üzerinden bu Context sınıfı Concrete State‘lere erişim sağlayabilmektedir.

Evet, bu bir öncekine nazaran daha doğru bir tasarımsal kodlamadır 🙂

Bunlar da hoşunuza gidebilir...

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir