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ı
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.