Fading Coder

One Final Commit for the Last Sprint

Home > Tools > Content

Adapter Pattern

Tools 1

Type

Structural

Difficulty

★☆☆☆☆ (Low)

Definition

Convert an interface in to another interface clients expect, enabling incompatible classes to collaborate. Also known as Wrapper, it encapsulates a target class with a new layer, embodying the principle: "No problem can't be solved by adding one layer."

Use Cases

  • When using an existing class with an incompatible interface, and modifying it is not feasible.
  • When integrating independently developed modules with undetermined interfaces during initial design.

UML Roles

The pattern involves three core components:

  • Target: Interface expected by client code.
  • Adaptee: Existing class/interface with incompatible interface; provides required functionality.
  • Adapter: Implements Target interface, wraps Adaptee to bridge compatibility gaps.

Implementation Example

Consider integrating a third-party logging library with an application's existing logger interface.

Step 1: Define Target Interface

Application's original logger contract:

public interface AppLogger {
    void logDebug(String category, String content);
}

Step 2: Third-Party Logger Interface & Implementation

Incompatible external logger API:

public interface ExternalLogger {
    void writeLog(int level, String msg, Object... args);
}

public class ExternalLoggerImpl implements ExternalLogger {
    @Override
    public void writeLog(int level, String msg, Object... args) {
        System.out.printf("External Logger: %s%n", msg);
    }
}

Step 3: Create Adapter Class

Bridges AppLogger and ExternalLogger:

import java.util.Objects;

public class LoggerAdapter implements AppLogger {
    private final ExternalLogger externalLogger;

    public LoggerAdapter(ExternalLogger externalLogger) {
        this.externalLogger = Objects.requireNonNull(externalLogger);
    }

    @Override
    public void logDebug(String category, String content) {
        // Map app's debug call to external logger's level 1 (debug)
        externalLogger.writeLog(1, content);
    }
}

Step 4: Client Usage

public class LoggerClient {
    public void executeLogging() {
        AppLogger logger = new LoggerAdapter(new ExternalLoggerImpl());
        logger.logDebug("System", "Integration test via adapter");
    }
}

Key Technical Points

  • Adapter must implement the Target interface.
  • Adapter holds a reference to the Adaptee instance to delegate functionalitty.

Pros and Cons

Pros

  • Enhances extensibility: Integrates new features without modifying existing interfaces.

Cons

  • Introduces an additional abstraction layer, which may marginally increase complexity.

Related Articles

Efficient Usage of HTTP Client in IntelliJ IDEA

IntelliJ IDEA incorporates a versatile HTTP client tool, enabling developres to interact with RESTful services and APIs effectively with in the editor. This functionality streamlines workflows, replac...

Installing CocoaPods on macOS Catalina (10.15) Using a User-Managed Ruby

System Ruby on macOS 10.15 frequently fails to build native gems required by CocoaPods (for example, ffi), leading to errors like: ERROR: Failed to build gem native extension checking for ffi.h... no...

Resolve PhpStorm "Interpreter is not specified or invalid" on WAMP (Windows)

Symptom PhpStorm displays: "Interpreter is not specified or invalid. Press ‘Fix’ to edit your project configuration." This occurs when the IDE cannot locate a valid PHP CLI executable or when the debu...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.