Chain Of Responsibility Design Pattern (Sorumluluk Zinciri Tasarım Deseni)

Design Patterns Çağrı ŞİŞMAN 22.8.2016

 

Chain of Responsibility (Sorumluluk Zinciri) tasarım deseni, davranışsal (behavioral) tasarım desenlerinden biridir. Özellikle loglama,hata yönetimi vb. işlerde çeşitli kurallara bağlı kod yönlendirme işlemlerini gerçekleştirmek amacıyla kullanılan tasarım desenlerinden biridir. Bunu biraz açalım.

Örneğin banka pos servisleri ile entegre olan ve ödeme işlemlerini gerçekleştiren bir uygulama yazıyoruz fakat burada bazı kurallarımız ve önceliklerimiz var. 

 

- Önceliğimiz A bankası ile işlem gerçekleştirmek. Fakat A bankası ile işlem gerçekleştirmeye çalışırken bir hata olursa B bankasının posuna ödeme yapılması gerekiyor. B bankası posunda da bir hata oldu diyelim o zaman C bankasının posuna gitmeliyiz. Onda da diyelim ki hata aldık, artık yapacak fazla bir şeyimiz yok :)

Şaka bir yana bu şekilde kurallara bağlı pek çok işlemi kodlamamız gerekebilir. Bu durumda ne yapabiliriz?

a) If-else blokları ile bodoslama yazarak halledebiliriz gibi duruyor ama öok sayıda if-else bloğu kullanabiliriz, SOLID'e ters gibi duruyor.

b) Belki de bu tip işler için kullanabileceğimiz bir tasarım şablonu vardır. Belki bu işlemleri (A,B,C) bankaları için ayrı bir sınıf yapabilseydik, A sınıfı B sınıfını durumdan haberdar edebilseydi, duruma göre aynı şekilde B sınıfı da C sınıfına haber verebilrseydi, bu nesneler arasında bir zincir kurup istemci ile servis arasında soyutlanmış bir yapı kurabilseydik güzel olabilirdi.

İşte bu tasarım deseninin sırrı b şıkkında duruyor.

public abstract class PosHandler
{

    protected PosHandler NextHandler;

    public PosHandler NextPosHandler
    {
        set { NextHandler = value; }
    }


    public abstract void Pay(string cardNumber, string cvv, string cardName, decimal price);

}

Banka posları ile işlem yapacak sınıflar ise aşağıdaki gibi tanımlanabilir.

public class ABankPosHandler:PosHandler
{
    public override void Pay(string cardNumber, string cvv, string cardName, decimal price)
    {

        try
        {
            int sayi = 0;
            int sayi2 = 100/sayi;
            Console.WriteLine("A Bankası ile ödeme gerçekleşti");
        }
        catch
        {
            NextHandler.Pay(cardNumber, cvv, cardName, price);
        }


    }
}

 

 

public class BBankPosHandler:PosHandler
{
    public override void Pay(string cardNumber, string cvv, string cardName, decimal price)
    {

        try
        {
             //B bankası ile ilgili işlemler
        }
        catch
        {
            NextHandler.Pay(cardNumber, cvv, cardName, price);
        }


    }
}

 

public class CBankPosHandler:PosHandler
{
    public override void Pay(string cardNumber, string cvv, string cardName, decimal price)
    {

        try
        {
            //C Bankası ile ilgili işlemler
        }
        catch
        {
            // C banka posu ile ilgili bir sıkıntı olursa artık başka bir sınıf olmadığından burası duruma göre handle edilir.
        }


    }
}

 

,Şimdi zincirimizi kurabiliriz. 

 

var aBankPosHandler=new ABankPosHandler();
var bBankPosHandler=new BBankPosHandler();
var cBankPosHandler=new CBankPosHandler();

aBankPosHandler.NextPosHandler = bBankPosHandler;
bBankPosHandler.NextPosHandler = cBankPosHandler;

aBankPosHandler.Pay("12313","123","cagri sisman",1500);

 

Eğer A banka pos ile bir hata olursa B Posuna, B posunda bir hata olursa C posuna gidecek. Böyle bir zincir kurmuş olduk. A posunda hata almasını sağlayarak sonuca bakacak olursak B Bankası ile işlem gerçekleşti çıktısını alırız.

 


Etiketler: C#