The Adapter pattern is a design pattern that allows incompatible interfaces to work together. It acts as a bridge between two interfaces, enabling them to communicate effectively. The Adapter pattern is particularly useful when you want to integrate new classes into existing code that relies on a specific interface or when you need to make incompatible interfaces compatible.

Key Characteristics:

  • Interface Compatibility: Adapts one interface to another, allowing classes with incompatible interfaces to work together.
  • Wrapper: Wraps an object to conform to a different interface.
  • Decoupling: Promotes loose coupling between clients and the classes they interact with.

How It Works:

  1. Target Interface: Defines the interface that the client expects.
  2. Adapter: Implements the target interface and translates requests to the adaptee.
  3. Adaptee: The class with the existing interface that needs adapting.
  4. Client: Interacts with the target interface, unaware of the adapter’s existence.

Example in PHP:

  // Target Interface
interface Target {
    public function request();
}

// Adaptee Class
class Adaptee {
    public function specificRequest() {
        return "Specific request from Adaptee.";
    }
}

// Adapter Class
class Adapter implements Target {
    private $adaptee;

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

    public function request() {
        // Translate request to the adaptee's specific request
        return $this->adaptee->specificRequest();
    }
}

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

// Usage
$adaptee = new Adaptee();
$adapter = new Adapter($adaptee);
clientCode($adapter); // Output: Specific request from Adaptee.
  

Explanation:

  1. Target Interface: Target defines the interface that the client code expects (request()).
  2. Adaptee: Adaptee is an existing class with a different interface (specificRequest()).
  3. Adapter: Adapter implements the Target interface and translates the request from the Target interface to the Adaptee’s interface.
  4. Client: The client code interacts with the Target interface, using the adapter to work with the Adaptee.

Benefits:

  • Compatibility: Allows classes with incompatible interfaces to work together.
  • Flexibility: Enables integration of new classes into existing codebases without altering the original code.
  • Decoupling: Reduces the dependency between client code and the specific implementations of classes.

Use Cases:

  • Legacy Systems: When integrating legacy systems with new systems that have different interfaces.
  • Third-Party Libraries: When using third-party libraries with interfaces that do not match your application’s requirements.

The Adapter pattern provides a way to make disparate systems work together by adapting their interfaces, making it a valuable tool for integrating and managing compatibility between different components or systems.