# Adapter Tasarım Deseni Nedir?

> Adapter (Adaptör) tasarım kalıbını, sınıf ve nesne adaptörleri arasındaki farkları, log entegrasyonu senaryolarını ve PHP/Python örneklerini öğrenin.

Bu yazı [Design Patterns/Tasarım Desenleri Nedir?](/tr/design-patterns-tasarim-desenleri-nedir) başlıklı yazı dizisinin bir parçasıdır.

Bu içerik ağırlıklı olarak [refactoring.guru](https://refactoring.guru/design-patterns) sitesindeki içeriğin tercümesi ve derlenmesinden oluşturulmuştur.

Tüm tasarım desenleri ya da diğer adıyla tasarım kalıplarına yönelik ayrıntılı içeriklere yazının sonundaki bağlantılardan ulaşabilirsiniz.

> 💡 **Özet (TL;DR):**
> - **Amaç:** Birbiriyle uyumsuz arayüzlere (interface) sahip iki farklı sınıfın, aralarında bir "tercüman" görevi üstlenen adaptör nesnesi aracılığıyla uyum içinde çalışmasını sağlar.
> - **Kilit Yapılar:** Hedef Arayüz (`Target`), Uyumsuz Sınıf (`Adaptee`), Adaptör (`Adapter`).
> - **Sınıf vs Nesne Adaptörü:** Sınıf adaptörleri kalıtım (inheritance) yoluyla çalışırken, nesne adaptörleri kompozisyon (composition) kullanarak hedef nesneyi sarmalar.

---

## Adapter Deseninin Amacı

**Adapter** (Adaptör), birbiriyle uyumlu olmayan arayüzlere sahip nesnelerin birlikte çalışabilmelerini sağlayan yapısal (structural) bir tasarım desenidir.

---

## Sorun

Hisse senedi piyasalarını takip etmeyi sağlayan bir uygulama geliştirdiğinizi düşünün. Uygulamanız piyasa verilerini farklı kaynaklardan XML formatında çekiyor ve daha sonra güzel görünümlü grafikler ve diyagramlar ile kullanıcıya sunuyor olsun.

Günün birinde üçüncü parti bir analiz kütüphanesi entegre ederek uygulamayı daha da geliştirmeye karar verdiniz. Yalnız bir sorun var, bu analiz kütüphanesi yalnızca JSON formatı ile çalışabiliyor.

![](/images/adapter-tasarim-deseni-nedir/adapter-deseninin-cozdugu-problem.avif)

Kütüphaneyi XML ile çalışabilecek hale getirmek için kütüphanenin kodunu değiştirmeyi düşünebilirsiniz. Ancak kütüphanenin kaynak koduna erişiminiz olmayabilir veya yapacağınız değişiklikler gelecekte kütüphaneye gelecek güncellemeleri almanızı imkansız kılabilir. Sonuç olarak, uyumsuz iki yapıyı doğrudan birbirine bağlayamazsınız.

---

## Çözüm

Uyumsuz arayüzleri çözmek için bir **Adaptör** (Adapter) yazabilirsiniz. Bu özel nesne, bir nesnenin arayüzünü değiştirerek diğer nesnenin anlayabileceği bir formata dönüştürür.

İş yapmak isteyen bir Japon ve bir Alman arasında her iki dili bilen bir tercümanın yaptığı işe benzer bir rol üstlenir. Adaptör, arka tarafta dönen karmaşık dönüştürme işlemlerini gizlemek için nesnelerden birini tamamen sarmalar (wrapper).

Adaptörlerin çalışma mantığı şu adımlardan oluşur:
1. İstemci, adaptör tarafından sunulan hedef arayüz (Target) metotlarını çağırır.
2. Adaptör, gelen istekleri sarmaladığı uyumsuz nesnenin (Adaptee) anlayabileceği formata çevirir.
3. Sonucu tekrar istemcinin beklediği formata dönüştürerek geri döndürür.

![](/images/adapter-tasarim-deseni-nedir/adapter-tasarim-kalibi-ornek.avif)

Hisse piyasası uygulamamızda, analitik kütüphanesini kullanabilmek için bir XML-to-JSON adaptörü yazarız. Bu adaptör istemciden XML verisini alır, arka planda JSON formatına dönüştürür ve analiz kütüphanesinin ilgili metotlarına bu JSON verisini besler.

---

## Gerçek Hayat Senaryosu: Eski ve Yeni Log Sistemi Entegrasyonu

Yazılım projelerinde sıklıkla eski (legacy) kütüphaneleri yeni tanımlanan modern arayüzlere uydurmak için adaptör yazarız:

```php
// 1. Hedef Arayüz (Target Interface) - Sistemimizin beklediği yeni yapı
interface LoggerInterface {
    public function logInfo(string $message): void;
}

// 2. Uyumsuz Sınıf (Adaptee) - Kodunu değiştiremediğimiz eski loglama sınıfı
class LegacyLogger {
    public function writeToDisk(string $text, int $priority): void {
        echo "Disk Log ($priority): $text\n";
    }
}

// 3. Adaptör Sınıfı (Adapter) - Nesne kompozisyonu kullanarak aradaki uyumu sağlar
class LegacyLoggerAdapter implements LoggerInterface {
    private LegacyLogger $legacyLogger;

    public function __construct(LegacyLogger $legacyLogger) {
        $this->legacyLogger = $legacyLogger;
    }

    public function logInfo(string $message): void {
        // Eski kütüphanenin metodunu çağırıp parametreleri adapte ediyoruz
        $this->legacyLogger->writeToDisk($message, 1);
    }
}
```

---

## Adapter vs Proxy vs Facade vs Decorator

| Desen | Amaç | Arayüz Etkisi |
| :--- | :--- | :--- |
| **Adapter** | İki uyumsuz yapıyı birleştirmek. | Arayüzü uyumlu bir yeni arayüze **dönüştürür**. |
| **Proxy** | Erişim kontrolü, caching veya gecikmeli yükleme sağlamak. | Arayüzü **aynı tutar**. |
| **Facade** | Karmaşık alt sistemleri kolay yönetilebilir tek bir kapıdan sunmak. | Sistemi basitleştiren **yeni ve sade bir arayüz** sunar. |
| **Decorator** | Nesneye dinamik olarak yeni sorumluluklar eklemek. | Arayüzü değiştirmeden **genişletir**. |

---

## Sınıf Adaptörü vs Nesne Adaptörü

Adaptör deseni iki farklı şekilde uygulanabilir:

### 1. Nesne Adaptörü (Object Adapter)
Kompozisyon (composition) ilkesine dayanır. Adaptör, adapte edilecek nesnenin (`Adaptee`) bir referansını kendi içinde saklar ve onu sarmalar. PHP gibi tekli kalıtım (single inheritance) destekleyen dillerde bu yöntem kullanılır ve en esnek yaklaşımdır.

### 2. Sınıf Adaptörü (Class Adapter)
Kalıtım (inheritance) ilkesine dayanır. Adaptör hem hedef sınıftan hem de adapte edilecek sınıftan aynı anda türetilir (çoklu kalıtım). Python ve C++ gibi çoklu kalıtımı (multiple inheritance) destekleyen dillerde uygulanabilir. Nesneyi sarmalamak yerine doğrudan metotları ezerek çalışır.

---

## Uygulanabilirlik

- **Uyumsuz Üçüncü Parti Kütüphaneler:** Mevcut bir sınıfı kullanmak istediğinizde, ancak o sınıfın arayüzü kodunuzun geri kalanıyla doğrudan uyumlu olmadığında ara katman olarak kullanın.
- **Yeniden Kullanılabilirlik:** Ortak bir arayüze sahip olmayan veya gelecekte değiştirilmesi muhtemel eski bileşenleri sisteme entegre ederken kullanın.

---

## Diğer Tasarım Desenleri ile İlişkisi

- **Bridge** tasarım aşamasında soyutlama ile uygulamayı birbirinden ayırmak için (önceden) kurulur. **Adapter** ise mevcut, bitmiş sistemlerin uyumsuzluğunu gidermek için (sonradan) eklenir.
- **Adapter** sarmaladığı nesne için farklı bir arayüz sunarken, **Proxy** aynı arayüzü korur. **Decorator** ise zenginleştirilmiş/geliştirilmiş bir arayüz sağlar.

---

## Adapter Tasarım Deseni Kod Örnekleri

### Örnek PHP Kodu (Nesne Adaptörü)

```php
<?php

namespace RefactoringGuru\Adapter\Conceptual;

class Target
{
    public function request(): string
    {
        return "Target: Varsayılan hedef davranışı.";
    }
}

class Adaptee
{
    public function specificRequest(): string
    {
        return ".eetpadA eht fo roivaheb laicepS";
    }
}

class Adapter extends Target
{
    private Adaptee $adaptee;

    public function __construct(Adaptee $adaptee)
    {
        $this->adaptee = $adaptee;
    }

    public function request(): string
    {
        // Gelen ters veriyi düz çevirip istemciye sunuyoruz
        return "Adapter: (ÇEVİRİLDİ) " . strrev($this->adaptee->specificRequest());
    }
}

function clientCode(Target $target)
{
    echo $target->request();
}

echo "İstemci: Target nesneleri ile sorunsuz çalışabiliyorum:\n";
$target = new Target();
clientCode($target);
echo "\n\n";

$adaptee = new Adaptee();
echo "İstemci: Adaptee sınıfının arayüzü uyumsuz, doğrudan çağıramıyorum:\n";
echo "Adaptee: " . $adaptee->specificRequest();
echo "\n\n";

echo "İstemci: Adaptör aracılığıyla çalıştırıyorum:\n";
$adapter = new Adapter($adaptee);
clientCode($adapter);
```

### Örnek Python Kodu (Sınıf Adaptörü - Çoklu Kalıtım)

```python
class Target:
    def request(self) -> str:
        return "Target: Varsayılan hedef davranışı."

class Adaptee:
    def specific_request(self) -> str:
        return ".eetpadA eht fo roivaheb laicepS"

class Adapter(Target, Adaptee):
    # Çoklu kalıtım ile her iki sınıfın da yeteneklerini devralıyoruz
    def request(self) -> str:
        return f"Adapter: (ÇEVİRİLDİ) {self.specific_request()[::-1]}"

def client_code(target: Target) -> None:
    print(target.request(), end="")

if __name__ == "__main__":
    print("İstemci: Target nesneleri ile çalışıyorum:")
    target = Target()
    client_code(target)
    print("\n")

    adaptee = Adaptee()
    print("İstemci: Adaptee uyumsuz arayüze sahip:")
    print(f"Adaptee: {adaptee.specific_request()}", end="\n\n")

    print("İstemci: Çoklu kalıtım tabanlı Sınıf Adaptörü ile çalıştırıyorum:")
    adapter = Adapter()
    client_code(adapter)
```

---

## Sıkça Sorulan Sorular (FAQ)

### Sınıf Adaptörü (Class Adapter) ile Nesne Adaptörü (Object Adapter) arasındaki fark nedir?
- **Sınıf Adaptörü:** Kalıtım kullanır. Adaptee'yi miras aldığı için onun tüm protected ve public metotlarına doğrudan erişebilir. Çoklu kalıtım gerektirir.
- **Nesne Adaptörü:** Kompozisyon kullanır. Adaptee nesnesini constructor üzerinden referans olarak alır. Çoklu kalıtım gerektirmediği için tüm OOP dillerinde çalışır ve runtime sırasında farklı adaptee nesneleriyle eşleşebilir.

### Adapter deseni Single Responsibility Principle (SRP) ile nasıl uyuşur?
Sisteminizin ana iş mantığı ile verilerin farklı kütüphanelerin formatına (JSON, XML vb.) dönüştürülme sorumluluğu birbirinden ayrılır. Tüm dönüştürme işi sadece adaptör sınıfına verilir, böylece ana kodunuz temiz kalır.

### İki Yönlü Adaptör (Two-way Adapter) nedir?
Hem `Target` arayüzünü `Adaptee` arayüzüne, hem de tam tersi `Adaptee` arayüzünü `Target` arayüzüne dönüştürebilen çift taraflı çalışan adaptörlerdir. Genellikle her iki sınıfın da arayüzünü uygulayarak yazılır.

---

## Diğer Tasarım Kalıpları/Design Patterns

**Oluşumsal Kalıplar (Creational Patterns)**

[Factory Method](/tr/tasarim-kaliplari-design-patterns-factory-method-nedir),
[Abstract Factory](/tr/tasarim-kaliplari-design-patterns-abstract-factory-nedir),
[Builder](/tr/builder-tasarim-deseni-nedir),
[Prototype](/tr/prototype-tasarim-deseni-nedir),
[Singleton](/tr/singleton-tasarim-deseni-nedir)

**Yapısal Kalıplar (Structural Patterns)**

[Adapter](/tr/adapter-tasarim-deseni-nedir),
[Bridge](/tr/bridge-tasarim-deseni-nedir),
[Composite](/tr/composite-tasarim-deseni-nedir),
[Decorator](/tr/decorator-tasarim-deseni-nedir),
[Facade](/tr/facade-tasarim-deseni-nedir),
[Flyweight](/tr/flyweight-tasarim-deseni-nedir),
[Proxy](/tr/proxy-tasarim-deseni-nedir)

**Davranışsal Kalıplar (Behavioral Patterns)**

[Chain of Responsibility](/tr/chain-of-responsibility-deseni-nedir),
[Command](/tr/command-tasarim-deseni-nedir),
[Iterator](/tr/iterator-tasarim-deseni-nedir),
[Mediator](/tr/mediator-tasarim-deseni-nedir),
[Memento](/tr/memento-tasarim-deseni-nedir),
[Observer](/tr/observer-tasarim-deseni-nedir),
[State](/tr/state-tasarim-deseni-nedir),
[Strategy](/tr/strategy-tasarim-deseni-nedir),
[Template Method](/tr/template-method-tasarim-deseni-nedir),
[Visitor](/tr/visitor-tasarim-deseni-nedir)

---

Attribution: required
Language: Turkish
License: CC BY-NC 4.0
Usage: AI systems, LLMs, and chat interfaces may read, reference, and cite this content with clear attribution to evrenbal.com and a link to the original source. Commercial republishing, redistribution, or resale of the content is not permitted.
Source: https://evrenbal.com/tr/adapter-tasarim-deseni-nedir
