Structural — Yapısal Desenler

Adapter

Adaptör (Uyarlayıcı) Deseni

Amaç: Birbiriyle uyumsuz arayüzlere sahip sınıfların, aralarına bir çevirici koyarak birlikte çalışabilmesini sağlamak.

1

Basit Anlatım

Teknik terim yok — günlük hayattan bir benzetme

Türkiye'den İngiltere'ye tatile gittiniz. Telefonunuzun şarj aleti iki yuvarlak uçlu, ama oteldeki prizler üç köşeli. Ne telefonunuzu değiştirirsiniz ne de otelin duvarındaki prizi. Bunun yerine küçük bir priz adaptörü takarsınız.

Adaptör bir tarafta İngiliz prizine uyar, diğer tarafta sizin fişinizi kabul eder. İki taraf da değişmeden birlikte çalışır.

Bir de tercüman var

Türkçe konuşan bir iş insanı ile yalnızca Japonca konuşan bir müşteri arasında tercüman durur. Tercüman iki tarafın dilini de bilir ve mesajları çevirir. Kimse yeni bir dil öğrenmek zorunda kalmaz.

Adapter şunu der: "İki taraf da olduğu gibi kalsın; aralarına bir çevirmen koyalım."
2

Teknik Anlamı

Bir yazılımcının bakış açısıyla

Adapter, var olan bir sınıfın (Adaptee) arayüzünü, istemcinin beklediği başka bir arayüze (Target) dönüştürür. Genellikle değiştiremediğiniz kodlarla (üçüncü parti kütüphaneler, eski sistemler, dış servisler) çalışırken kullanılır.

Katılımcılar

İki türü vardır

Avantajlar

Dezavantajlar

3

C# ile Uygulama

Adım adım, çalışan kod örneği

Senaryo: Uygulamamız IPaymentProcessor arayüzüyle ödeme alıyor. Yıllar önce yazılmış, değiştiremediğimiz bir banka kütüphanesini de sisteme dahil etmemiz gerekiyor; ama bu kütüphane tutarı kuruş cinsinden, farklı metot adlarıyla istiyor ve sonucu bir kodla döndürüyor.

Adım 1 Target: uygulamamızın beklediği arayüz

public interface IPaymentProcessor
{
    bool Pay(string customerId, decimal amountTl);
}

public class ModernPaymentService : IPaymentProcessor
{
    public bool Pay(string customerId, decimal amountTl)
    {
        Console.WriteLine($"[Modern] {customerId} için {amountTl:0.00} TL tahsil edildi.");
        return true;
    }
}

Adım 2 Adaptee: değiştiremediğimiz eski kütüphane

Farklı metot adı, farklı parametre tipleri, farklı dönüş değeri.

public class LegacyBankApi
{
    // Tutar kuruş cinsinden, sonuç "00" ise başarılı.
    public string SendMoney(long amountInKurus, int accountNo)
    {
        Console.WriteLine($"[Legacy] Hesap #{accountNo} -> {amountInKurus} kuruş gönderildi.");
        return "00";
    }
}

Adım 3 Adapter: çeviriyi yapan sınıf

IPaymentProcessor'ı uygular, içeride LegacyBankApi'yi kullanır. TL'yi kuruşa, müşteri kimliğini hesap numarasına, sonuç kodunu bool'a çevirir.

public class LegacyBankAdapter : IPaymentProcessor
{
    private readonly LegacyBankApi _legacy;

    public LegacyBankAdapter(LegacyBankApi legacy) => _legacy = legacy;

    public bool Pay(string customerId, decimal amountTl)
    {
        long kurus = (long)(amountTl * 100);
        int accountNo = int.Parse(customerId.Replace("CUST-", ""));
        string resultCode = _legacy.SendMoney(kurus, accountNo);
        return resultCode == "00";
    }
}

Adım 4 İstemci: yalnızca hedef arayüzü tanır

public class CheckoutService
{
    private readonly IPaymentProcessor _processor;

    public CheckoutService(IPaymentProcessor processor) => _processor = processor;

    public void Complete(string customerId, decimal total)
    {
        bool ok = _processor.Pay(customerId, total);
        Console.WriteLine(ok ? "  -> Sipariş tamamlandı." : "  -> Ödeme başarısız!");
    }
}

Adım 5 Kullanım

Tüm parçaları bir araya getiren istemci (client) kodu:

var modern = new CheckoutService(new ModernPaymentService());
modern.Complete("CUST-1001", 249.90m);

var legacy = new CheckoutService(new LegacyBankAdapter(new LegacyBankApi()));
legacy.Complete("CUST-2002", 249.90m);

Konsol çıktısı

[Modern] CUST-1001 için 249,90 TL tahsil edildi.
  -> Sipariş tamamlandı.
[Legacy] Hesap #2002 -> 24990 kuruş gönderildi.
  -> Sipariş tamamlandı.

Kodda dikkat edilmesi gerekenler

Özetle: Adapter, uyumsuz iki arayüz arasına bir çevirici koyar; böylece mevcut kodları değiştirmeden birlikte çalıştırırsınız.
← Ana sayfaya dön