# Adapter Pattern

> Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.

## Problem

You have a `LegacyPrinter` with a `print_old(text)` method, but your application expects a `Printer` interface with a `print(text)` method. You cannot modify the legacy code.

## Solution

Create an `Adapter` class that implements the target `Printer` interface and internally delegates to the `LegacyPrinter`'s incompatible method.

```
┌────────┐       ┌─────────────────┐       ┌───────────────┐
│ Client  │──────▶│  Printer (intf) │       │ LegacyPrinter │
│         │       │  + print(text)  │       │ + print_old() │
└────────┘       └─────────────────┘       └───────────────┘
                          ▲                        ▲
                          │                        │
                 ┌────────┴────────┐               │
                 │ PrinterAdapter   │───────────────┘
                 │ + print(text)    │  delegates to print_old()
                 └─────────────────┘
```

## When to Use

- You need to use an existing class but its interface doesn't match what you need.
- You want to create a reusable class that cooperates with unrelated or unforeseen classes.
- You need to integrate third-party or legacy code without modifying it.

## When to Avoid

- The interfaces are already compatible — just use the object directly.
- You can modify the source of the incompatible class (refactor instead).
- The adaptation is so complex that a full rewrite would be simpler.

## Pseudocode

```
interface Printer:
    method print(text)

class LegacyPrinter:
    method print_old(text):
        output "[Legacy] " + text

class PrinterAdapter implements Printer:
    field legacy: LegacyPrinter

    constructor(legacy):
        this.legacy = legacy

    method print(text):
        legacy.print_old(text)

// Usage
legacy = new LegacyPrinter()
adapter = new PrinterAdapter(legacy)
adapter.print("Hello, Adapter!")
```

## Python

```python
from abc import ABC, abstractmethod


class Printer(ABC):
    """Target interface the client expects."""

    @abstractmethod
    def print(self, text: str) -> None: ...


class LegacyPrinter:
    """Existing class with an incompatible interface."""

    def print_old(self, text: str) -> None:
        print(f"[Legacy] {text}")


class PrinterAdapter(Printer):
    """Adapter that wraps LegacyPrinter to satisfy the Printer interface."""

    def __init__(self, legacy: LegacyPrinter) -> None:
        self._legacy = legacy

    def print(self, text: str) -> None:
        self._legacy.print_old(text)


def client_code(printer: Printer) -> None:
    """Client only knows about the Printer interface."""
    printer.print("Hello from the client!")


if __name__ == "__main__":
    legacy = LegacyPrinter()
    adapter = PrinterAdapter(legacy)

    print("--- Direct legacy call ---")
    legacy.print_old("direct call")

    print("\n--- Through adapter ---")
    client_code(adapter)
```

**Output:**
```
--- Direct legacy call ---
[Legacy] direct call

--- Through adapter ---
[Legacy] Hello from the client!
```

## Go

```go
package main

import "fmt"

// Target interface the client expects.
type Printer interface {
	Print(text string)
}

// LegacyPrinter has an incompatible method name.
type LegacyPrinter struct{}

func (lp *LegacyPrinter) PrintOld(text string) {
	fmt.Printf("[Legacy] %s\n", text)
}

// PrinterAdapter adapts LegacyPrinter to the Printer interface.
type PrinterAdapter struct {
	legacy *LegacyPrinter
}

func NewPrinterAdapter(legacy *LegacyPrinter) *PrinterAdapter {
	return &PrinterAdapter{legacy: legacy}
}

func (a *PrinterAdapter) Print(text string) {
	a.legacy.PrintOld(text)
}

// clientCode only depends on the Printer interface.
func clientCode(p Printer) {
	p.Print("Hello from the client!")
}

func main() {
	legacy := &LegacyPrinter{}
	adapter := NewPrinterAdapter(legacy)

	fmt.Println("--- Direct legacy call ---")
	legacy.PrintOld("direct call")

	fmt.Println("\n--- Through adapter ---")
	clientCode(adapter)
}
```

**Output:**
```
--- Direct legacy call ---
[Legacy] direct call

--- Through adapter ---
[Legacy] Hello from the client!
```

## JavaScript

```javascript
// Target interface expectation: object with print(text)

class LegacyPrinter {
  printOld(text) {
    console.log(`[Legacy] ${text}`);
  }
}

class PrinterAdapter {
  constructor(legacyPrinter) {
    this._legacy = legacyPrinter;
  }

  print(text) {
    this._legacy.printOld(text);
  }
}

function clientCode(printer) {
  printer.print("Hello from the client!");
}

// --- Main ---
const legacy = new LegacyPrinter();
const adapter = new PrinterAdapter(legacy);

console.log("--- Direct legacy call ---");
legacy.printOld("direct call");

console.log("\n--- Through adapter ---");
clientCode(adapter);
```

**Output:**
```
--- Direct legacy call ---
[Legacy] direct call

--- Through adapter ---
[Legacy] Hello from the client!
```

## Related Patterns

- **Facade** — Adapter translates one interface; Facade simplifies a complex subsystem. An Adapter for a complex system can look like a Facade.
- **Decorator** — Decorator adds behavior while preserving interface; Adapter changes the interface without adding behavior.
- **Proxy** — Proxy preserves the interface and controls access; Adapter changes the interface.
- **Bridge** — Adapter reconciles existing incompatible interfaces; Bridge separates abstraction from implementation from the start.
- **Strangler Fig** — Adapter is the key tool in Strangler Fig migration: the new interface is an Adapter over the old one.
