Proxy Design Pattern

Proxy Design Pattern

Proxy tasarım deseni, structural grubuna ait oluşturulması karmaşık veya oluşturulması zaman alan işlemlerin kontrolünü sağlar. Dofactory.com a göre kullanım sıklığı %80 civarındadır ve yapı bakımından basittir.

Proxy tasarım deseni çalışma maliyeti yüksek işlemlerin olduğu yapılarda, web servisi kullanılan yapılarda, remoting uygulamalarında, operasyonun gerçekleştirilmesinden önce hazırlık yapılması veya ön işlem yapılması durumlarında kullanılır. Uygulanışı basit bir tasarım desenidir. Uml diyagramı aşağıdadır.

Uml diyagramındaki Subject yapısı interface veya abstract sınıf olarak tasarlanır ve gerçekleştirilecek operasyonların tanımını belirtir. RealSubject ve Proxy ise gerçek sınıflardır. RealSubject sınıfı operasyonu gerçekleştirecek gerçek kodları barındırır. Proxy sınıfı ise RealSubject sınıfındaki operasyonları çalıştırır. Yani burada proxy nesnesi client ve operasyonu gerçekleştirecek metotların arasında bulunan bir yapı görevi görür.

Yani, pattern olarak bir objeyi temsil eden başka bir objeden bahsediyoruz.  Kullanım senaryolarından biri de , bir classımız ve bunun bir nesnesi olduğunu varsayalım. Bu nesne bir okula ait tüm sınıf öğrencilerinin tüm bilgilerini tutuyor olsun. Aldıkları dersleri, derslerden aldıkları puanları, kaldıkları dersleri, isimlerini, soyisimlerini, doğum tarihlerini, ailelerinin isim, soyisim ve kimlik bilgilerini ve her bir işlem yaptığımızda bu okul öğrencilerini bir tur dönüyor ve gerekli bilgileri içerisinde barındırıyor olsun. Ancak bizim client olarak tüm bu bilgilerden ziyade belli başlı sınıfların belli başlı özelliklerine ve bilgilerine ihtiyacımız olabilir. Bu durumda proxy class oluşturup sadece belli başlı metotlara ve üyelere erişim izni verebiliriz ve client bu nesneyi kopyaladığında orjinal nesneyi kopyalamasına kıyasla çok daha az bir maliyet ile işi halletmiş olur.

Aşağıdaki örnek uygulamamızın senaryosu resim gösterimi üzerine olsun. Gerçekte gösterilecek resimer büyük boyutta olsun ve kullanıcıya resmi gösterirken ilk sefer hariç, resimler yüklenirken geçen zamanı save edebilmek için proxy class yazalım. Tabi ki kodlarımızın uzamaması için sadece konsol ekranına yazı yazdıracağız. Örnek uygulamanın sınıf diyagramı aşağıdadır.

Aşağıda örnek uygulamamız bulunmaktadır. Uygulamada IımageGenerator adındaki interface bizim real subjectimiz ve proxyi classımızın ortak bir dil konuşmasını sağlayacak yani bizim real subjectimiz de image generatorümüz de bu interface’i implemente edecektir.

 public interface IImageGenerator
 {
    void ShowImage();
 }

Aşağıda Image generator adında real subjectimiz vardır. Bu class esas işi yapacak olan classtır ve IımageGeneratorü implemente eder.

  public class ImageGeneratorIImageGenerator
  {
     private string _fullPath;

     public ImageGenerator(string fullPath)
     {
        _fullPath = fullPath;
     }
     public void ShowImage()
     {
       Console.WriteLine("{0} Resim Gösteriliyor..",_fullPath);
     }
}

Aşağıda ImageGeneratorProxy classımız vardır ve bu class da IımageGeneratoru imlepemente eder ve ImageGenerator classına vekillik eder. Gördüğünüz gibi classın yaptığı gerçek classa vekalet etmek ve ilgili özelliklerini kullanıcıya sunmaktır.


 public class ImageGeneratorProxy : IImageGenerator
 {
        private ImageGenerator _generator;
        private string _fullPath;

        public ImageGeneratorProxy(string fullPath)
        {
            _fullPath = fullPath;
        }

        public void ShowImage()
        {
            if (_generator == null)
                _generator = new ImageGenerator(_fullPath);

            _generator.ShowImage();
        }
  }

Aşağıda da proxy classın client tarafından kullanımı görülmektedir.

   class Program
   {
       static void Main(string[] args)
       {
          ImageGeneratorProxy proxy1 = new ImageGeneratorProxy("c:\\resim1.jpg");
          ImageGeneratorProxy proxy2 = new ImageGeneratorProxy("c:\\resim2.jpg");

          proxy1.ShowImage();
          proxy2.ShowImage();
          proxy1.ShowImage();

          Console.ReadKey();
       }
   }