The Adapter pattern is a structural design pattern that allows objects with incompatible interfaces to work together. It acts as a bridge, converting the interface of a class into another interface that a client expects. This pattern is useful when integrating new systems or components that need to interact with existing codebases.

Key Characteristics:

  • Interface Transformation: Adapts one interface to another, enabling compatibility between disparate systems.
  • Wrapper: Wraps an existing object to conform to a different interface.
  • Loose Coupling: Promotes flexibility by decoupling the client from the specifics of the adapted object.

How It Works:

  1. Target Interface: The interface that the client code expects and interacts with.
  2. Adapter: Implements the target interface and translates client requests to the adaptee’s interface.
  3. Adaptee: The existing class with an incompatible interface that needs to be adapted.
  4. Client: Uses the target interface and interacts with the adapter without knowing about the adaptee.

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 expected by the client (request()).
  2. Adaptee: Adaptee is an existing class with a different interface (specificRequest()).
  3. Adapter: Adapter implements the Target interface and translates the request() method to specificRequest() of Adaptee.
  4. Client: The client code interacts with the Target interface, using the adapter to handle requests to the Adaptee.

Benefits:

  • Compatibility: Allows integration of classes with incompatible interfaces.
  • Flexibility: Facilitates interaction between systems with different interfaces without modifying their code.
  • Encapsulation: Hides the complexities of the adaptee from the client code.

Use Cases:

  • Integrating Legacy Systems: When you need to integrate older systems or libraries that have different interfaces.
  • Working with Third-Party Libraries: When third-party libraries use interfaces that do not match your application’s needs.

The Adapter pattern helps in making disparate systems compatible by adapting their interfaces, enabling smoother integration and interaction between different components or systems.