Tasarım Kalıpları: Proxy (Vekil) – IV
Proxy tasarım kalıbıyla ilgili bir önceki yazıda, bu kalıp ile ilgili ikinci örneğimizi, ağ yapılarındaki proxy kullanımını simule etmiştik çünkü bizim yazılımda proxy kalıbıyla yapmaya çalıştığımız şey aslında yıllardır ağlarda güvenlik amacıyla kontrol ve filtreleme yapan proxylerin yaptığı şeydi. Şimdi bu konudaki son örneğimizle devam edelim.
GoF kitaplarında, proxy kalıbıyla ilgili örnek olarak içerisinde büyük hacimli resimlerin (image) olduğu bir metin dokümanını verir. Örnek yapıda, metin dokümanı açılırken yani belleğe yüklenirken, içerisinde var olan büyük hacimli resimlerin de yüklenmesini istemenin ciddi bir yaratma ve yükleme maliyeti yaratacağından bahsedilir. Bundan dolayı teklif edilen, metni görüntüleyenin, dokümanda gerçekten bu resimlere gelinceye kadar, resimlerin yüklenmesini geciktirmektir. Muhakkak böye bir yaklaşım metni daha hızlı belleğe yükleyecek ve kullanıcının metin üzerinde dolaşmasını ve onu kullanmasını daha rahat kılacaktır. Bu durumda yapılacak şey, metin dokümanı yüklenirken, resimlerin doğrudan belleğe yüklenmesi yerine, proxy yani, o resimler yerine geçen vekil nesnelerin ya da daha açık ifadeyle örneğin ikon gibi, İngilizce’de “placeholder” denen, o resmin olduğunu belirten “yer tutucu”ların yüklenmesidir. Yer tutucu nesne aşağıdaki şekilde “anImageProxy” olarak görüntülenmiştir.
Bu noktada dikkat edilmesi gereken şey, gerçek resimler yerine yer tutucuların yüklendiğini, metnin bilmemesi gerektiğidir. Bu şekilde yer tutucu yani vekil resim (burada sanırım vekillikten ziyade “göstermelik” kelimesi daha anlamlı oluyor) kullanmanın, metnin yapısında hiç bir değişikliğe sebep olmaması gereklidir. Bunu sağlamanın yöntemi ise gerçek nesne ile vekilinin aynı arayüze sahip olmasıdır. Eğer bu nokta atlanırsa, proxy nesnesi, doğrudan arada bulunan ve varlığından özellikle vatandaş ya da bu örnekteki metin dokümanı gibi müşteri (client) nesnelerinin tamamen haberdar olduğu, basit al-ver (delegation) yapan nesneye dönüşür ki bu durumda da zaten “program to an interface, not an implementation” prensibini ıskalamış oluruz.
Bu kalıp bu olaya uygulandığında aşağıdaki diyagrama ulaşırız:
Yukarıdaki şekile bakarken, GoF’un kitabı yazılırken UML’in henüz tamamlanmadığı gerçeğini göz önüne almalıyız. Ayrıca GoF örneklerini C++ ile verdiklerinden şekildeki kod parçaları bu dildedir. Biz bu yapıyı Java ile yazarsak kodlarımız şöyle olacaktır:
Image, arayüzdür:
package org.javaturk.dp.pattern.gof.structural.proxy.image; public interface Image { public void draw(); public void erase(); }
BigImage, yüklenmesini geciktirdiğimiz büyük resim nesnemizdir.
package org.javaturk.dp.pattern.gof.structural.proxy.image; public class BigImage implements Image { public void draw() { System.out.println("Drawing the big image"); } public void erase() { System.out.println("Erasing the big image"); } }
ImageProxy ise vekil resim nesnesidir:
package org.javaturk.dp.pattern.gof.structural.proxy.image; public class ImageProxy implements Image { private BigImage bigImage; public void draw() { if(bigImage == null) bigImage = new BigImage(); bigImage.draw(); } public void erase() { bigImage.erase(); } }
ImageChooser ise singleton resim gösteren nesnedir.
package org.javaturk.dp.pattern.gof.structural.proxy.image; public class ImageChooser { private static ImageChooser ic = new ImageChooser(); private Image image; public ImageChooser(){ image = new ImageProxy(); } Image getImage(){ return image; } public static ImageChooser getInstance(){ return ic; } }
Document ise, sadece main metoda sahip olan metin nesnemizdir:
package org.javaturk.dp.pattern.gof.structural.proxy.image; public class Document { public static void main(String[] args) { ImageChooser imageChooser = ImageChooser.getInstance(); Image image = imageChooser.getImage(); double chance = Math.random(); if(chance > 0.9) image.draw(); } }
Document nesesinin main metodundaki “if” yapısı, gerçekte BigImage nesnesinin yüklenmesinin sanki %10’luk bir ihtimal dahilinde olacağını göstermek için konmuştur.
Toplam görüntülenme sayısı: 1338