1. Proxy Tasarım Deseni Nedir

Proxy deseni, belirli bir nesneye erişimi kontrol etmek için bir vekil olarak hareket eden yapısal bir tasarım desenidir. Hedef nesneye (vâki olan nesne) dayalı olarak, vekil deseni istemcilerin hedef nesneye erişebileceği bir vekil nesne sağlar, böylece hedef nesneye ek işlevsellik eklenmesine izin verir.

1.1 Proxy Deseni Tanımı

Proxy deseni, iki veya daha fazla nesnenin işbirliğini içeren bir tasarım desenidir. Bir nesne gerçek hedef nesne çağrılmaktayken, bir veya daha fazla diğer nesne vekil nesne olarak hareket eder. Vekil nesneler, hedef nesneye erişimi engeller ve ona dolaylı bir şekilde erişim sağlar.

1.2 Proxy Deseni Amaçları ve Hedefleri

Proxy deseninin temel amacı, hedef nesneye dolaylı bir şekilde erişim sağlayarak, hedef nesneye ek işlevsellik eklenmesine izin vermektir. Vekil nesneler, hedef nesneye erişimi kontrol etme, önbelleğe alma ve günlükleme gibi ortak mantığı işleyebilir. Proxy deseni ayrıca tembel yükleme uygulayabilir ve hedef nesneyi sadece ihtiyaç duyulduğunda yaratır.

2. Proxy Deseni Özellikleri ve Avantajları

Proxy deseninin aşağıdaki özellikleri ve avantajları vardır:

  • Hedef nesnenin işlevselliğini değiştirmeden genişletebilir.
  • Hedef nesneye vekil nesne aracılığıyla erişimi kontrol edebilir.
  • Hedef nesneye erişmeden önce veya sonra ek işlemler gerçekleştirebilir.
  • Tembel yükleme uygulayabilir ve hedef nesneyi sadece ihtiyaç duyulduğunda yaratabilir.

3. Proxy Deseni Pratik Uygulama Örnekleri

Proxy deseni birçok uygulama senaryosunda yaygın olarak kullanılır. İşte pratik uygulama örneklerinin bazı ortak örnekleri:

  • Uzak Vekil: Ağdaki nesnelere yerel erişim için kullanılır.
  • Sanal Vekil: Gerektiğinde pahalı nesneler oluşturmak için kullanılır.
  • Güvenlik Vekil: Nesnelere erişimi kontrol etmek için kullanılır.
  • Akıllı Referans: Nesnelere erişirken nesne sayma gibi ek işlemler gerçekleştirmek için kullanılır.

4.1 UML Sınıf Diyagramı

Aşağıda Golang'da Proxy Deseni için UML sınıf diyagramı bulunmaktadır:

Golang Proxy Deseni

4.2 Örnek Tanıtımı

Varsayalım ki Subject adında bir arayüzümüz var ve bu arayüzün bir Request methodunu tanımladığını düşünelim. RealSubject adında arayüzü uygulayan somut bir uygulama sınıfımız var. Daha sonra RealSubject nesnesini tutan ve aynı zamanda Subject arayüzünü uygulayan Proxy adında bir vekil sınıf oluşturuyoruz. Proxy sınıfının Request methodunda, RealSubject'in Request methodunu çağırmadan önce veya sonra ek işlemler gerçekleştirebiliriz.

4.3 Uygulama Adımı 1: Vekil Arayüzünü Tanımlama

İlk olarak, bir Request methodu içeren Subject arayüzünü tanımlamamız gerekiyor:

package main

type Subject interface {
    Request()
}

4.4 Uygulama Adımı 2: Hedef Nesneyi Uygulama

Daha sonra, Subject arayüzünü uygulayan belirli hedef nesne RealSubject'i uyguluyoruz:

package main

import "fmt"

type RealSubject struct {}

func (r *RealSubject) Request() {
    fmt.Println("RealSubject: İsteği İşleme")
}

4.5 Uygulama Adımı 3: Vekil Nesneyi Uygulama

Daha sonra, RealSubject nesnesini tutan ve Subject arayüzünü uygulayan Proxy adında bir vekil nesnesi oluşturuyoruz. Proxy'ın Request methodunda, RealSubject'ın Request methodunu çağırmadan önce veya sonra ek işlemler gerçekleştirebiliriz:

package main

import "fmt"

type Proxy struct {
    realSubject *RealSubject
}

func (p *Proxy) Request() {
    fmt.Println("Proxy: Önceki İsteği")
    
    if p.realSubject == nil {
        p.realSubject = &RealSubject{}
    }
    
    p.realSubject.Request()
    
    fmt.Println("Proxy: Sonraki İsteği")
}

4.6 Uygulama Adımı 4: Vekil Nesneyi Çağırma

Son olarak, vekil nesne Proxy'i kullanarak, vekil nesnenin yönlendirdiği nesnenin yöntemlerini çağırabiliriz:

package main

func main() {
    proxy := Proxy{}
    proxy.Request()
}

Yukarıdaki kodu çalıştırmak, aşağıdaki çıktıyı üretecektir:

Proxy: Önceki İsteği
RealSubject: İsteği İşleme
Proxy: Sonraki İsteği

5.1 Proxy Pattern ve Decorator Pattern Arasındaki Fark ve Bağlantı

Proxy pattern ve decorator pattern, ikisi de yapısal tasarım desenleri olan birer hedef nesne ve birer proxy/dekoratör nesnesi içeren desenlerdir. Bununla birlikte, ikisi arasında bazı farklılıklar vardır:

  • Proxy pattern genellikle hedef nesneye erişim kontrolünü içerirken, decorator pattern daha çok hedef nesneyi genişletmeye odaklanır.
  • Proxy pattern genellikle hedef nesneden önce veya sonra ek işlemler gerçekleştirirken, decorator pattern dinamik olarak hedef nesnenin üzerine ekstra işlevsellik ekler.

5.2 Statik Proxy ve Dinamik Proxy Karşılaştırması

Proxy pattern, statik proxy ve dinamik proxy olmak üzere ikiye ayrılabilir. Statik proxy, derleme zamanında proxy nesnesinin türünü belirler ve proxy nesnesi programcı tarafından manuel olarak yazılır. Diğer yandan dinamik proxy, hedef nesnenin arayüzüne bağlı olarak çalışma zamanında proxy nesnesini dinamik olarak oluşturur. Dinamik proxy, esnek ancak statik karşılaştırıldığında daha karmaşık bir yapıya sahiptir.

5.3 Proxy Pattern'in Mikrohizmetlerde Uygulanması

Proxy pattern, mikrohizmet mimarisinde uygulanabilir. Örneğin, bir proxy kullanarak diğer mikrohizmetlere erişimi kapsayabilir ve proxy katmanında yük dengeleme, sınırlandırma ve devre dışı bırakma gibi mekanizmaları uygulayabiliriz. Bu, sistemdeki güvenilirliği ve performansı artırabilir. Proxy pattern ayrıca servis keşfi ve yönlendirme işlevselliğini uygulamak için de kullanılabilir.