1. Zincir Sorumluluk Deseni Nedir

Zincir Sorumluluk Deseni, bir davetin göndereni ve alıcısını ayırarak, bir isteği işleme şansı veren birden fazla nesnenin birbirinden bağımsız olmasını sağlayan davranışsal bir tasarım desenidir. Her alıcı diğer bir alıcıya referans içerir ve isteği işleyemezse isteği sıradaki alıcıya ileterek isteğin işlenmesini veya zincirin sonuna ulaşmasını sağlar.

2. Zincir Sorumluluk Deseni Özellikleri ve Avantajları

Zincir Sorumluluk Deseninin özellikleri ve avantajları aşağıdaki gibidir:

  • Gönderen ve alıcının ayrılması: Gönderen, isteği hangi alıcının işlediğini ve zincirdeki belirli işleyicileri bilmesine gerek yoktur.
  • Esneklik: Gönderen ve alıcı kodunu değiştirmeden zincirde işleyicilerin dinamik olarak eklenmesine, kaldırılmasına veya yeniden düzenlenmesine izin verir.
  • Genişletilebilirlik: Yeni belirli işleyiciler ekleyerek sorumluluk zincirini genişletmek kolaydır.
  • Tek Sorumluluk Prensibi: Her belirli işleyicinin sadece kendi işleme mantığıyla ilgilenmesi gerekir.
  • Yapılandırılabilirlik: İhtiyaca göre işleyicilerin zinciri yapılandırılabilir, böylece farklı isteklerin farklı işleyici zincirlerine sahip olmasına izin verir.

3. Zincir Sorumluluk Deseni Pratik Uygulama Örnekleri

Zincir Sorumluluk Deseni, kimlik doğrulama, günlükleme ve izin doğrulama gibi farklı türde istekleri işlemek için web uygulamalarında, hata işleme, her işleyicinin gerektiği gibi belirli hata türlerini işlemek ve gerektiğinde hatayı bir sonraki işleyiciye iletmek için kullanılabilir. Ayrıca kullanıcı tıklama olayları, ağ istek olayları gibi farklı türde etkinlikleri işlemek için kullanılabilir.

4. Golang'da Zincir Sorumluluk Deseninin Uygulanması

4.1 UML Sınıf Diyagramı

Golang Zincir Sorumluluk Deseni

4.2 Örnek Giriş

Yukarıdaki UML sınıf diyagramında, soyut bir işleyici (Handler) ve iki somut işleyici (ConcreteHandler1 ve ConcreteHandler2) tanımladık. İstemci (Client), işleyicinin handleRequest yöntemini çağırarak istekleri başlatır.

4.3 Uygulama Adımı 1: Soyut İşleyici Arayüzünü Tanımlama

type Handler interface {
    HandleRequest(request Request) error
    SetNext(handler Handler)
}

type Request interface {
    Condition bool
}

Soyut işleyici arayüzü, istekleri işlemek için HandleRequest yöntemini ve bir sonraki işleyiciyi ayarlamak için SetNext yöntemini tanımlar.

4.4 Uygulama Adımı 2: Somut İşleyici Sınıflarını Uygulama

type ConcreteHandler1 struct {
    next Handler
}

func (h *ConcreteHandler1) HandleRequest(request Request) error {
    // İsteği işleme mantığı
    if request.Condition {
        // İsteği işlemek için kod
        return nil
    } else {
        if h.next != nil {
            return h.next.HandleRequest(request)
        }
        return errors.New("İşleyici bulunamadı")
    }
}

func (h *ConcreteHandler1) SetNext(handler Handler) {
    h.next = handler
}

type ConcreteHandler2 struct {
    next Handler
}

func (h *ConcreteHandler2) HandleRequest(request Request) error {
    // İsteği işleme mantığı
    if request.Condition {
        // İsteği işlemek için kod
        return nil
    } else {
        if h.next != nil {
            return h.next.HandleRequest(request)
        }
        return errors.New("İşleyici bulunamadı")
    }
}

func (h *ConcreteHandler2) SetNext(handler Handler) {
    h.next = handler
}

Somut işleyici sınıfları, soyut işleyici arayüzünü uygular ve HandleRequest ve SetNext yöntemlerini geçersiz kılar.

4.5 Uygulama Adımı 3: Zincir Sorumluluğunun Oluşturulması

handler1 := &ConcreteHandler1{}
handler2 := &ConcreteHandler2{}

handler1.SetNext(handler2)

Somut işleyicileri örnekleyerek ve bir sonraki işleyiciyi ayarlayarak bir zincir sorumluluğu oluşturulur.

4.6 Uygulama Adımı 4: İstemci Kodu

func main() {
    handler := &ConcreteHandler1{}

    // Zincir sorumluluğunun oluşturulması
    handler.SetNext(&ConcreteHandler2{})

    // Bir istek gönderme
    handler.HandleRequest(Request{Condition: true})
}

İstemci kodunda, bir somut işleyici örneklendi, sonraki işleyici ayarlandı ve ardından HandleRequest yöntemi çağrılarak bir istek gönderildi.