Birbirinden farklı interface‘lere sahip -dolayısıyla ilişkisiz denebilecek- sınıfları birlikte kullanmak istediğimizde bu desenimizi uygularız. Bu deseni iki şekilde gerçekleştirebiliriz. İlki Class Adapter olarak adlandırılır. Bir interface'i implemente ederek gerçekleştirir. İkincisi ise Object Adapter olarak adlandırılır. İnterface yerine bir obje kullanılır. Aşağıda her iki yöntemin de literatürdeki şemaları verilmiştir.

şekil 1. Class Adapter – Çoklu Miras Yoluyla
şekil 1'de istemci hedeften bir istekte bulunur. Hedeften türetilmiş olan Adapter sınıfından ise bu istek talep edilir. Adapter sınıfı kendine özgü bu isteği Adaptee sınıfından implemente ederek gerçekleştirmiştir. Sonuç olarak Adapter sınıfı bu özel isteği implemente ederek kendisinde barındırır.

şekil 1. Object Adapter – Nesne Komposizyonu Yoluyla
şekil 2'de istemci hedeften bir istekte bulunur. Yine hedeften türetilmiş olan Adapter sınıfından bu istek talep edilir. Bu sefer bu özel istek Adapter sınıfının üyesi olan Adaptee sınıfından elde edilir. Yani bu isteği Adaptee sınıfı barındırır. Bu yapı ise Object kompozisyonu olarak adlandırılır.
Somut bir örnek ile konumuzu daha yakından inceleyelim. Senaryomuz ise şu şekilde;
şekil çizebildiğimiz iki panelimiz olacak. Bu panellerden ilki Class Adapter yöntemiyle , ikincisi Object Adapter yöntemiyle tasarlanacaktır. Programın ana ekranı şekil 3'te görüldüğü gibidir.

şekil 3. Programın Ana Ekranı
Burada istemcilerimiz panel, hedef sınıfımız şekil, istek fonksiyonumuz çiz, Adapter sınıfımız dikdörtgen, Adaptee sınıfımız ise dikdörtgen çizici sınıflarıdır.
Buna göre soyut sınıfımız olan Sekil sınıfı aşağıdaki gibidir. İstek fonksiyonumuz ise yine soyut olan ciz() fonksiyondur.
abstract public class Sekil{
public Sekil() {
}
abstract public void ciz();
}
Class Adapter
Adaptee interface'i bizim senaryomuzda class adapter için CDikdortgenCizici interface'idir. Bu interface'imiz özel istek fonksiyonumuz olan dikdorgenCiz() fonksiyonumuzu tanımlamaktadır.
public interface CDikdortgenCizici {
public void dikdorgenCiz();
}
Aşağıdaki kodumuzda ise adapter sınıfımıza denk gelen CDiktorgen sınıfımız bulunmaktadır. Bu sınıfımız Sekil sınıfdan türemekle birlikte CDikdortgenCizici interface'ini de implemente etmektedir. Atasının çiz fonksiyonunu override ederek özel istek fonksiyonunu(dikdorgenCiz()) çağırır. Bu fonksiyon ise CDikdortgenCizici interface'inden implemente edilir.
public class CDiktorgen extends Sekil implements CDikdortgenCizici{
private JPanel p;
private Rectangle r;
public CDiktorgen(JPanel p,Rectangle r) {
this.p = p;
this.r = r;
}
public void ciz() {
dikdorgenCiz();
}
public void dikdorgenCiz() {
Graphics g = p.getGraphics();
g.drawRect((int)r.getX(),(int)r.getY(),
(int)r.getWidth(),(int)r.getHeight());
}
}
Böylelikle bir CDiktorgen nesnesi oluşturup ciz isteği istendiğinde aşağıdaki yapı ile gerçekleştirilir.
sekil = new CDiktorgen(cPanel, new Rectangle(x,y, width, height));
sekil.ciz();
Object Adapter
Bu yaklaşımda ise Adaptee sınıfı bizim senaryomuza göre ODikdortgenCizici sınıfına denk düşmektedir.
ODikdortgenCizici yapıcısında çizceği dikdörtgeni ve çizeceği paneli almaktadır. Sonrasında dikdorgenCiz()metodu ile istenildiğinde bu dikdörtgeni panel çizmektedir.
public class ODikdortgenCizici {
private JPanel p;
private Rectangle r;
public ODikdortgenCizici(JPanel p,Rectangle r) {
this.p = p;
this.r = r;
} public void dikdorgenCiz(){
Graphics g = p.getGraphics();
g.drawRect((int)r.getX(),(int)r.getY(),
(int)r.getWidth(),(int)r.getHeight());
}
}
Adapter sınıfına denk gelen ODikdortgen sınıfı da bir önceki tasarımdaki CDikdortgen sınıfı gibi şekil sınıfından türetilmektedir. Yalnız buradaki sınıfımız bir interface'i implemente etmek yerine ODikdortgenCizici sınıfını bir member olarak barındırmakta ve çizim işlerini bu sınıf üzerinden yapmaktadır.
public class ODikdortgen extends Sekil{
private ODikdortgenCizici cizici;
public ODikdortgen(JPanel p,Rectangle r) {
cizici = new ODikdortgenCizici(p,r);
}
public void ciz(){
cizici.dikdorgenCiz();
}
}
Bir önceki tasarıma benzer şekilde bir ODiktorgen nesnesi oluşturup ciz isteği istendiğinde aşağıdaki yapı ile gerçekleştirilir.
sekil = new ODikdortgen(oPanel, new Rectangle(x,y, width, height));
sekil.ciz();
Sonuç ve Değerlendirme
Birbirinden yapısal bakımdan farklı olan sınıfların kullanımı sağlamak için Adapter tasarım deseni kullandık. Bu desenimizi iki yöntemle örneklendirdik. İlki Class Adapter olarak adlandırılan ve temeli interface'e dayanan bir yap idi. İkincisi ise Object Adapter olarak adlandırılan ve temeli miras almaktan ziyade nesne kompozisyonuna dayanan bir yapı idi. Duruma ve probleme göre bu iki yapıdan biri tercih edilebilir.
Makalede verilen örneğin proje(Netbeans 4.1 kullandım) dosyasını tyklayarak indirebilirsiniz. Proje içersinde ..\src\ klasörünün altında kaynak kodları , ..\dist\ klasörünün altında da çalıştırılabilir jar dosyası bulunmaktadır.
Kaynaklar:
[1] The Design Patterns by James W. COOPER
[2] Elements of Reusable Object-Oriented Software by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides

[
14.10.2005]