C# Proxy Design Pattern(Proxy Tasarım Deseni)
Merhaba,
Bu makalemizde Structural Patterns(Yapısal Desenler) kategorisine giren Proxy Design Pattern hakkında teferruatlı bir içerik oluşturacağız.
Oluşturduğumuz tasarımda bazı sınıfların, nesnelerin yahut işleyişlerin sorumluluk ve süreçteki işlevsel hallerini bir başka nesne üzerinde kontrol edebilir ve sorumluluğu bu nesneye yükleyebiliriz. Daha net bir ifadeyle, nesnelerin süreçteki vekaletini başka bir sınıfa devredebiliriz. İşte bu yazımızda da bu bahsettiğim algoritmanın deseninden yani Proxy Design Pattern’den bahsediyor olacağız.
Bu tarz bir uygulamayı tasarım desenini bilmeden de hemen hemen çoğumuzun gerçekleştirmiş olması muhtemeldir. Eee, hepimiz bir çok Design Pattern’i farkında olmaksızın önceden kullandığımızı sonradan desenleri öğrenirken görmüşüzdür. D.P. yapıları, belirli durumlarda tekrarlanan ve kalıp olarak ihtiyaç duyulan noktada uygulanabilen manevralardan ibarettir ve tek bir dile bağımlılığı yoktur. Ondandır ki tasarım deseni dediğimiz olgu, “Aklın yolu birdir” sözünü oldukça doğrulamaktadır.
Şimdi Proxy tasarımını incelemeye başlayalım.
Proxy D.P. Client tarafından erişilecek nesneye vekalet eden bir tasarım desenidir. Burada vekaletten kasıt ilgili nesneyi kontrol edecek bir Proxy nesnesinin kullanılmasıdır.
Üç farklı durumda Proxy D.P. kullanılır.
- Remote(Uzak) Proxy
Remote(uzak) bir nesne kullanılacağı durumlarda kullanılabilir. Uzaktaki nesneye local bir temsilci sağlar ve gerekli kontrolleri yapmamıza olanak tanır. - Virtual Proxy
Üretimi yahut kullanımı maliyetli nesnelerin oluşturulması veya kullanılması için tercih edilir. Buna örnek olarak genelde herkesin dillendirdiği resim yükleme işlevini verebiliriz. Yüksek boyutlu bir resmin boyutundan dolayı geç yüklenmesi durumunda verilen -yükleniyor- mesajı ve ardından yükleme işlemi bittiği anda resmin gösterilmesinde kullanılabilir. - Protection Proxy
Yetkilendirme yahut login durumlarında kullanılabilir.
Proxy desenini uygularken bu üç duruma genel olarak aşağıdaki terminolojiyle hareket edilecektir.
- Client
İstemcidir. - Subject
İstemcinin tek bir tip ile çalışmasını sağlayacak olan Interface yahut abstract class’ımızdır. Real Subject ve Proxy nesnelerimizin türediği yapıdır. - Real Subject
O anki işin asıl çalışmasını gerçekleştirecek olan gerçek nesnemizdir. - Proxy
Vekil sınıfımızdır. İçerisinde Real Subject referansını taşıyarak istemcinin isteklerine cevap verecektir. Doğal olarak istemci gerçek nesneye dolaylı yoldan Proxy üzerinden erişebilecektir.
Şimdi Proxy D.P’i örneklendirelim.
Öncelikle Protection Proxy‘ye özel örneklendirme yapalım. Örneğimizde gerekli hesap girişi yapıldığı taktirde bir banka üzerinden para gönderme işlemini gerçekleştirelim.
Aşağıdaki kodları inceleyiniz.
Öncelikle Subject Class’ımızı oluşturalım.
//Subject Class interface IBanka { bool OdemeYap(double Tutar); }
Ardından gerçek nesnemiz olan Real Subject’i oluşturalım.
//Real Subject Class class Banka : IBanka { public bool OdemeYap(double Tutar) { if (Tutar < 100) Console.WriteLine($"Ödeyeceğiniz tutar 100 TL'den az olamaz. Fark -> { 100 - Tutar }"); else if (Tutar > 100) Console.WriteLine($"Ödeyeceğiniz tutar 100 TL'den fazla olamaz. Fark -> { Tutar - 100 }"); else { Console.WriteLine($"Ödeme başarıyla gerçekleştirildi. -> { Tutar }"); return true; } return false; } }
Dikkat ederseniz Real Subject, Subject’ten türemekte ve artık hangi işlemi yapacaksanız o işlemi yapacak nesnenin ta kendisi olması gerekmektedir.
Şimdi Proxy’i inşa ederek, Client tarafından erişim sağlanacak vekil sınıfımızı oluşturalım.
//Proxy Class class ProxyBanka : IBanka { Banka banka; bool Login; string KullaniciAdi, Sifre; public ProxyBanka(string KullaniciAdi, string Sifre) { this.KullaniciAdi = KullaniciAdi; this.Sifre = Sifre; } bool GirisYap() { if (KullaniciAdi.Equals("gncy") && Sifre.Equals("1234")) { banka = new Banka(); Login = true; Console.WriteLine("Hesaba giriş yapıldı."); return true; } else Console.WriteLine("Lütfen kullanıcı adı ve şifreinizi doğru girdiğinize emin olunuz."); Login = false; return false; } public bool OdemeYap(double Tutar) { GirisYap(); if (!Login) { Console.WriteLine("Hesaba giriş yapılmadığından dolayı ödeme alamıyoruz."); return false; } banka.OdemeYap(Tutar); return true; } }
Burada dikkat etmeniz gereken husus, Protection Proxy‘e özel örneklendirme yaptığımız için yapılacak yetkilendirme işlemine uygun bir algoritma gerçekleştirdik.
Bu tasarıyı Client tarafında aşağıdaki gibi kullanabilmekteyiz.
//Client class Program { static void Main(string[] args) { string KullaniciAdi = "", Sifre = ""; double Tutar = 0; while (true) { Console.WriteLine("Lütfen kullanıcı adınızı giriniz."); KullaniciAdi = Console.ReadLine(); Console.WriteLine("Lütfen şifrenizi giriniz."); Sifre = Console.ReadLine(); Console.WriteLine("Lütfen ödenecek miktarı giriniz."); Tutar = Convert.ToInt32(Console.ReadLine()); IBanka banka = new ProxyBanka(KullaniciAdi, Sifre); banka.OdemeYap(Tutar); Console.WriteLine("************"); } } }
Örneklendirmemizde yapmış olduğum Proxy D.P.’in Client kodlarını biraz sadelikten uzak tuttuğumu kabul ediyorum. Sonsuz döngü içerisinde bir kullanım yapmamın sebebi aşağıdaki videoda olduğu gibi daha net bir test süreci geçirmemizi sağlamasından kaynaklanmaktadır.
Şimdide Virtual Proxy‘e özel bir örneklendirme yaparak konumuzu tamamlayalım. Virtual Proxy’ye özel senaryomuz ise yukarıda vermiş olduğumuz resim örneği olacaktır.
Örneğimizde kullanacağımız formun tasarımı yukarıdaki gibi olacaktır. Çalışmamızın tüm yapılarını aşağıda ele alalım.
//Subject Class interface IResim { void Goster(PictureBox pb, string Dizin); } //Real Subject Class class Resim : IResim { public void Goster(PictureBox pb, string Dizin) { pb.ImageLocation = Dizin; } } //Proxy Class class ProxyResim : IResim { Resim resim; bool ResimYuklendi; PictureBox pb; string Dizin; void ResimYukle(object o) { resim = new Resim(); resim.Goster(pb, Dizin); ResimYuklendi = true; } public void Goster(PictureBox pb, string Dizin) { this.pb = pb; this.Dizin = Dizin; if (resim == null) { new System.Threading.Timer(new TimerCallback(ResimYukle), this, 2000, 0); } if (!ResimYuklendi) { pb.ImageLocation = "D:\\Yukleniyor.gif"; } } }
Gördüğünüz gibi ProxyResim sınıfındaki Goster metodunda Real Subject referansı null ise bir Thread başlattık ve ResimYukle metodunu 2 saniyelik bir farkla tetiklettik. Bu sırada Thread tetiklenene kadar 2 saniye içerisinde alt satırları gelip gerekli if – else kontrolü sayesinde -yükleniyor- mesajını verecek resmi PictureBox nesnesinde gösterdik. ResimYukle metodu tetiklendiğinde ilgili referansa nesne bağlayarak referans üzerinden Goster metodunu tetikleyecektir ve asıl resmimiz ilgili nesnede gösterilecektir.
Sanırım Proxy Tasarım Kalıbınıda detaylıca irdelimiş olduk. Bol bol faydalanmanızı dilerim…
Okuduğunuz için teşekkür ederim.
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar dilerim…
Tesekkurler