Yazılım

Chain Of Responsibility Tasarım Deseni ve Uygulama Örneği

Kodnova 06 June 2026 9 görüntülenme
Chain Of Responsibility Tasarım Deseni ve Uygulama Örneği

Chain of Responsibility tasarım deseni, davranışsal tasarım kalıpları arasında yer alan ve bir isteğin birden fazla nesne tarafından işlenebileceği durumlarda kullanılan bir yazılım tasarım desenidir.

Bu desenin temel amacı, bir isteği doğrudan tek bir sınıfa bağımlı hale getirmek yerine, isteği işleyebilecek nesnelerden oluşan bir zincir oluşturmaktır. İstek zincirin ilk halkasına gönderilir. Her halka, isteği işleyip işleyemeyeceğine karar verir. Eğer işleyemiyorsa veya işlem tamamlandıktan sonra sürecin devam etmesi gerekiyorsa, isteği zincirdeki bir sonraki halkaya aktarır.

Bu yapı sayesinde istek gönderen kod ile isteği işleyen sınıflar arasındaki bağımlılık azaltılır. Böylece daha esnek, genişletilebilir ve bakımı kolay bir yapı elde edilir.

CHAIN OF RESPONSIBILITY TASARIM DESENİ NEDİR?

Chain of Responsibility, Türkçe karşılığıyla Sorumluluk Zinciri, bir işlemin birden fazla adımdan geçmesi gereken durumlarda oldukça kullanışlıdır. Her işlem adımı ayrı bir handler sınıfı olarak tasarlanır ve bu handler sınıfları birbirine zincir şeklinde bağlanır.

Bir istek zincirin başlangıç noktasına gönderildiğinde, her handler kendi sorumluluğunu yerine getirir. Eğer işlem başarılıysa istek bir sonraki handler sınıfına aktarılır. Eğer herhangi bir adımda işlem başarısız olursa zincir durdurulabilir.

Bu desen özellikle sipariş işlemleri, onay mekanizmaları, validasyon süreçleri, middleware yapıları, loglama zincirleri ve yetkilendirme kontrolleri gibi sıralı işlem adımlarının bulunduğu yapılarda tercih edilir.

PROBLEM

Bir e-ticaret sisteminde sipariş oluşturma sürecini düşünelim. Kullanıcının bir ürünü sipariş edebilmesi için birden fazla kontrolün yapılması gerekir.

Örneğin siparişin tamamlanabilmesi için öncelikle ürünün stokta olup olmadığı kontrol edilmelidir. Ardından kullanıcının adres bilgisinin geçerli olup olmadığı doğrulanmalıdır. Son olarak ödeme işlemi başarılı bir şekilde tamamlanmalıdır.

Bu kontrollerin tamamını tek bir sınıf içerisinde yapmak, kodun zamanla karmaşık hale gelmesine neden olur. Yeni bir kontrol eklenmek istendiğinde mevcut sınıf sürekli olarak değiştirilir. Bu da kodun bakımını zorlaştırır ve sınıfın tek sorumluluk prensibinden uzaklaşmasına yol açar.

ÇÖZÜM

Chain of Responsibility deseni ile her kontrol adımı ayrı bir sınıf olarak tasarlanır. Stok kontrolü, adres doğrulama ve ödeme kontrolü gibi işlemler kendi handler sınıflarında yönetilir.

Bu handler sınıfları birbirine zincir şeklinde bağlanır. Sipariş isteği ilk olarak stok kontrolünden geçer. Stok uygunsa adres kontrolüne aktarılır. Adres bilgileri geçerliyse ödeme kontrolüne geçilir. Tüm adımlar başarılı olursa sipariş işlemi tamamlanmış olur.

Bu yaklaşım sayesinde yeni bir kontrol adımı eklemek gerektiğinde mevcut akışı bozmadan yalnızca yeni bir handler sınıfı oluşturmak yeterli olur.

UYGULAMA ÖRNEĞİ

Bu örnekte, bir e-ticaret sisteminde ürün sipariş işlemlerini yönetmek için Chain of Responsibility tasarım desenini kullanacağız. Sipariş süreci üç temel adımdan oluşacak:

Stok kontrolü: Ürünün yeterli stokta olup olmadığı kontrol edilir.

Adres doğrulama: Müşterinin adres bilgisinin mevcut olup olmadığı kontrol edilir.

Ödeme kontrolü: Ödeme işleminin başarılı olup olmadığı doğrulanır.

ABSTRACT HANDLER CLASS

İlk olarak tüm işlem adımlarının temelini oluşturacak abstract bir sınıf tanımlıyoruz. Bu sınıf, zincirdeki bir sonraki handler bilgisini ayarlamak için SetNext metodunu ve ilgili işlemi gerçekleştirmek için Handle metodunu içerir.

Bu yapı sayesinde tüm handler sınıfları ortak bir sözleşmeye sahip olur. Yeni bir işlem adımı eklenmek istendiğinde bu abstract sınıftan türetilen yeni bir handler yazılması yeterlidir.


/// <summary>
/// Represents the base class for handling operations in a chain of responsibility.
/// Each handler in the chain can process an OrderItem or pass it to the next handler.
/// </summary>
public abstract class AbstractHandlerChain
{
    /// <summary>
    /// Sets the next handler in the chain of responsibility.
    /// This method should link this handler to another, forming a chain where an OrderItem
    /// can be passed along if not fully processed by this handler.
    /// </summary>
    public abstract Task SetNext(AbstractHandlerChain abstractHandlerChain);

    /// <summary>
    /// Handles the processing of an OrderItem.
    /// This method should implement the specific handling logic of the derived handler class.
    /// If the item cannot be fully processed, it may be passed to the next handler in the chain.
    /// </summary>
    public abstract Task<bool> Handle(OrderItem orderItem);
}

STOCK CONTROL

İlk handler sınıfımız stok kontrolünden sorumludur. Bu sınıf, sipariş edilen ürünün stokta yeterli miktarda olup olmadığını kontrol eder.

Eğer ürün stokta yeterli miktarda varsa, sipariş bir sonraki handler sınıfına aktarılır. Eğer stok yeterli değilse işlem başarısız kabul edilir ve zincir devam etmez.


/// <summary>
/// Handles stock control in a chain of responsibility pattern implementation.
/// This class checks if the required quantity of a product is available in stock
/// before passing the request to the next handler in the chain.
/// </summary>
public class StockControl : AbstractHandlerChain
{
    private AbstractHandlerChain _abstractHandlerChain;

    /// <summary>
    /// Sets the next handler in the chain of responsibility.
    /// </summary>
    public override async Task SetNext(AbstractHandlerChain abstractHandlerChain)
    {
        _abstractHandlerChain = abstractHandlerChain;
        await Task.CompletedTask;
    }

    /// <summary>
    /// Processes an order item by checking stock availability and, if sufficient stock exists,
    /// passing the order item to the next handler in the chain.
    /// </summary>
    public override async Task<bool> Handle(OrderItem orderItem)
    {
        var result = InMemoryDataForOrder.GetAllProductTotalQuantity();

        if (_abstractHandlerChain != null &&
            result.Count(x => x.ProductId == orderItem.ProductId) >= orderItem.Quantity)
        {
            return await _abstractHandlerChain.Handle(orderItem);
        }

        return false;
    }
}

ADDRESS VERIFICATION

Stok kontrolünden başarıyla geçen sipariş için bir sonraki adım adres doğrulamasıdır. Bu handler sınıfı, siparişi veren müşterinin adres bilgisinin mevcut olup olmadığını kontrol eder.

Eğer müşteri bilgisi bulunursa ve zincirde bir sonraki handler tanımlıysa, işlem bir sonraki adıma aktarılır. Eğer müşteri bilgisi bulunamazsa işlem başarısız olarak sonuçlanır.


/// <summary>
/// Handles the verification of customer address information as part of a chain of responsibility.
/// Ensures that a customer's address exists before allowing the handling of an order item
/// to continue in the chain.
/// </summary>
public class AddressControl : AbstractHandlerChain
{
    private AbstractHandlerChain _abstractHandlerChain;
    private int customerId;

    /// <summary>
    /// Initializes a new instance of the AddressControl class with a specified customer ID.
    /// </summary>
    public AddressControl(int customerId)
    {
        this.customerId = customerId;
    }

    /// <summary>
    /// Sets the next handler in the chain of responsibility.
    /// </summary>
    public override async Task SetNext(AbstractHandlerChain abstractHandlerChain)
    {
        _abstractHandlerChain = abstractHandlerChain;
        await Task.CompletedTask;
    }

    /// <summary>
    /// Processes the given order item by first verifying the associated customer's address.
    /// If the customer's address is valid, the processing is passed on to the next handler in the chain.
    /// </summary>
    public override async Task<bool> Handle(OrderItem orderItem)
    {
        var result = InMemoryDataForOrder.GetCustomerInformation(customerId);

        if (result != null && _abstractHandlerChain != null)
        {
            return await _abstractHandlerChain.Handle(orderItem);
        }

        return false;
    }
}

PAYMENT PROCESSING

Adres doğrulaması başarılı olduktan sonra son adım ödeme kontrolüdür. Bu handler sınıfı, ödeme işleminin başarılı olup olmadığını kontrol eder.

Gerçek bir uygulamada bu adımda banka, sanal POS veya ödeme sağlayıcısı gibi harici bir servis üzerinden ödeme doğrulaması yapılabilir. Bu örnekte ise ödeme kontrolü, örnek veri sağlayan bir metot üzerinden simüle edilmiştir.


/// <summary>
/// Handles payment verification in a chain of responsibility pattern implementation.
/// This class verifies the payment status of an order through an external API
/// before potentially passing the order item to the next handler in the chain.
/// </summary>
public class PaymentControl : AbstractHandlerChain
{
    private AbstractHandlerChain _abstractHandlerChain;

    /// <summary>
    /// Sets the next handler in the chain of responsibility.
    /// </summary>
    public override async Task SetNext(AbstractHandlerChain abstractHandlerChain)
    {
        _abstractHandlerChain = abstractHandlerChain;
        await Task.CompletedTask;
    }

    /// <summary>
    /// Processes an order item by checking the payment status through an API call.
    /// If the payment is verified, it may pass the order item to the next handler in the chain if one exists.
    /// </summary>
    public override async Task<bool> Handle(OrderItem orderItem)
    {
        // Verify payment through an external API
        return await Task.Run(() => InMemoryDataForOrder.PaymentCheckedFromAPI());
    }
}

CHAIN OF RESPONSIBILITY NASIL KULLANILIR?

Programın ana bölümünde öncelikle bir sipariş nesnesi oluşturulur ve bu siparişe bir ürün eklenir. Daha sonra stok kontrolü, adres kontrolü ve ödeme kontrolü için handler sınıfları oluşturulur.

Handler sınıfları SetNext metodu ile birbirine bağlanır. Böylece stok kontrolünden başlayan süreç, adres kontrolüne ve ardından ödeme kontrolüne doğru ilerler.


#region Chain of Responsibility Pattern Works

var order = new Order();

order.Items.Add(new OrderItem()
{
    ProductId = 1,
    Quantity = 1,
    UnitPrice = 100
});

var orderItem = order.Items.First();

var stockControl = new StockControl();
var addressControl = new AddressControl(1);
var paymentControl = new PaymentControl();

await stockControl.SetNext(addressControl);
await addressControl.SetNext(paymentControl);

var orderResult = await stockControl.Handle(orderItem);

Console.WriteLine(orderResult ? "Order is okay" : "Order is not okay");

#endregion

ÖNEMLİ NOT

Bu örnekte zinciri başlatmak için yalnızca ilk handler olan stockControl.Handle(orderItem) metodunu çağırmak yeterlidir. Çünkü stok kontrolü başarılı olursa işlem otomatik olarak adres kontrolüne, ardından ödeme kontrolüne aktarılır.

Bu nedenle her handler sınıfını ayrı ayrı çağırmaya gerek yoktur. Chain of Responsibility deseninin temel amacı da zaten sürecin zincir üzerinden tek bir başlangıç noktasıyla ilerlemesini sağlamaktır.

CHAIN OF RESPONSIBILITY TASARIM DESENİNİN AVANTAJLARI

Gevşek Bağlılık

İsteği gönderen kod, isteğin hangi sınıf tarafından işlendiğini bilmek zorunda değildir. Sadece zincirin başlangıç noktasına isteği gönderir. Bu da sınıflar arasındaki bağımlılığı azaltır.

Genişletilebilirlik

Sisteme yeni bir işlem adımı eklenmek istendiğinde mevcut handler sınıflarını değiştirmek gerekmez. Yeni bir handler sınıfı oluşturulup zincire dahil edilebilir.

Tek Sorumluluk Prensibine Uygunluk

Her handler yalnızca kendi sorumluluğundaki işlemi gerçekleştirir. Stok kontrolü, adres doğrulama ve ödeme kontrolü ayrı sınıflarda yönetildiği için kod daha okunabilir ve sürdürülebilir hale gelir.

İş Akışlarının Daha Kolay Yönetilmesi

Sıralı kontrollerden oluşan süreçlerde hangi adımın ne zaman çalışacağı daha net yönetilir. Bu da özellikle sipariş, onay, validasyon ve middleware yapılarında büyük avantaj sağlar.

SONUÇ

Chain of Responsibility tasarım deseni, bir isteğin birden fazla işlem adımından geçmesi gereken durumlarda esnek ve yönetilebilir bir yapı sunar.

Bu örnekte bir e-ticaret sipariş süreci üzerinden stok kontrolü, adres doğrulama ve ödeme kontrolü adımlarını ayrı handler sınıfları olarak ele aldık. Her handler yalnızca kendi sorumluluğunu yerine getirdi ve işlem başarılı olduğunda isteği zincirdeki bir sonraki adıma aktardı.

Bu yaklaşım sayesinde kod daha modüler, genişletilebilir ve bakımı kolay hale gelir. Özellikle e-ticaret sistemleri, validasyon süreçleri, onay mekanizmaları ve middleware yapıları gibi sıralı işlem akışlarının bulunduğu sistemlerde Chain of Responsibility deseni oldukça kullanışlıdır.

```

Benzer İçerikler

Factory Method Tasarım Deseni ve Uygulama Örneği
Yazılım

Factory Method Tasarım Deseni ve Uygulama Örneği

Factory Method Tasarım Deseni ve Uygulama Örneği

Kodnova 06 June 2026
Abstract Factory Tasarım Deseni ve Uygulama Örneği
Yazılım

Abstract Factory Tasarım Deseni ve Uygulama Örneği

Abstract Factory Tasarım Deseni ve Uygulama Örneği

Kodnova 06 June 2026
Adapter Tasarım Deseni ve Uygulama Örneği
Yazılım

Adapter Tasarım Deseni ve Uygulama Örneği

Adapter Tasarım Deseni ve Uygulama Örneği

Kodnova 06 June 2026
Hemen iletişime geç