Adaptör Kalıp (Adapter Pattern)

Eyl 08, 2013

Adaptör Kalıp, sadece bir sınıfa özel olan arayüzleri diğer sınıflarla uyumlu arayüzler haline getiren bir tasarım kalıbıdır. Adaptörler uyumlu olmayan arayüzler sebebiyle birbirleri ile çalışamayan sınıflara da birbirleri ile çalışma imkanı sunarlar.

Adaptör kalıbının özelliklerinden bazıları şunlardır:

  • Bir sınıfın arayüzünü istemcinin istediği yeni bir arayüze dönüştürme işlemi yapar.
  • Birbiriyle uyumsuz arayüzleri olan sınıfların birbiriyle çalışmasını sağlar.
  • Var olan sınıfı yeni bir arayüzle sarmalar.
  • Eski bir bileşeni yeni oluşturulan sisteme entegre eder.

Kullanıldığı durumlar:

Bazı durumlarda bir araç takımı (toolkit) ya da sınıf kütüphanesinin (framework) arayüzü uygulama için gerekli olan arayüz ile uyumsuz olduğu için kullanılamaz. Bu durumda kütüphane değiştirilmez, çünkü kaynak kodu bilinmiyor olabilir. Kaynak kodun bilindiği düşünülecek olsa bile her bir uygulama için tek tek kütüphaneyi değiştirmek doğru bir çözüm değildir. Adaptör kalıp bu gibi durumlarda devreye girmesi için geliştirilmiştir. Kısaca adaptör kalıp, kullanılmak istenen bir sınıfın kullanılacak arayüzün gereklilikleri ile eşleşmediği zamanlarda kullanılır.

Adaptör Kalıp UML Diyagramı

 

Örnek Uygulama:

using System;

namespace AdaptorKalıp
{
    class Program
    {
        static void Main(string[] args)
        {
            // Uyarlanmamış Kimyasal Bileşik
            Bilesik bilinmeyen = new Bilesik("Bilinmeyen bileşik");
            bilinmeyen.Goster();

            // Uyarlanmış Kimyasal Bileşik
            Bilesik su = new ZenginBilesik("su");
            su.Goster();

            Console.ReadKey();
        }
    }

    // "Target" Sınıfı
    class Bilesik
    {
        protected string kimyasal;
        protected string molekulFormulu;

        // Yapıcı (Constructor) Metod
        public Bilesik(string kimyasal)
        {
            this.kimyasal = kimyasal;
        }

        public virtual void Goster()
        {
            Console.WriteLine("\nKimyasal: {0} ", kimyasal);
        }
    }

    // Adaptör (Adapter) Sınıfı
    class ZenginBilesik : Bilesik
    {
        private KimyasalVeriBankası banka;

        // Yapıcı (Constructor) Metod
        public ZenginBilesik(string name)
            : base(name)
        {
        }

        public override void Goster()
        {
            // Adaptee
            banka = new KimyasalVeriBankası();

            molekulFormulu = banka.MolekulYapisiniGetir(kimyasal);

            base.Goster();
            Console.WriteLine("  Formül: {0}", molekulFormulu);
        }
    }

    // "Adaptee" Sınıfı
    class KimyasalVeriBankası
    {
        public string MolekulYapisiniGetir(string bilesik)
        {
            switch (bilesik.ToLower())
            {
                case "su": return "H20";
                default: return "";
            }
        }
    }
}

Yukarıdaki örnekte "Bilesik" isminde bir sınıf tanımlanmış ve bu sınıftan "ZenginBilesik" isminde bir adaptör sınıf türetilmiştir. Tanımlanan "KimyasalVeriBankası" sınıfı adapte edilecek olan sınıftır. "Bilesik" sınıfında tanımlanmış olan "Goster" metodu adaptör sınıfta tekrar tanımlanmıştır; çünkü "KimyasalVeriBankası" sınıfındaki "MolekulYapisiniGetir" metodu "Bilesik" sınıfında kullanılamayabilirdi. Bu nedenle "ZenginBilesik" isminde bir adaptör sınıf tanımlanarak "KimyasalVeriBankası" sınıfındaki veriler kullanılabilir hale getirilmiştir. Eğer "Bilesik" sınıfı kaynak kodu bilinmeyen bir sınıf olsaydı, yukarıdaki örnekteki gibi uyumlu olmayan sınıfları bir adaptör sınıf yardımıyla uyumlu hale getirilebilirdi.

Örnek Uygulama Çıktısı