Adapter Design Pattern (original) (raw)

Last Updated : 6 May, 2026

Adapter Design Pattern is a structural pattern that acts as a bridge between two incompatible interfaces, allowing them to work together. It is especially useful for integrating legacy code or third-party libraries into a new system.

Adapter-Design-Pattern

Adapter Design Pattern

In the above Diagram

Real-World Example

Adapter Design Pattern can be seen as a mobile adapter that helps in matching the device's power and voltage requirements. Similarly in software development, we use adapter for enabling interoperability between incompatible interfaces

Components

The components of adapter design pattern:

Working

The Working of adapter design pattern:

Uses

We can use adapter design pattern when:

Different implementations

The Adapter Design Pattern can be applied in various ways depending on the programming language and the specific context. Here are the primary implementations:

1. Class Adapter (Inheritance-based)

Uses inheritance to adapt the interface of an existing class to the target interface expected by the client.

2. Object Adapter (Composition-based)

Uses composition to wrap the adaptee object and provide the required interface to the client.

3. Two-way Adapter

Enables two different interfaces to work together by allowing conversion in both directions.

4. Interface Adapter (Default Adapter)

Provides default implementations for interface methods so only required methods need to be overridden.

Implementation Example

Understand adapter design pattern through an example:

Problem Statement

Let's consider a scenario where we have an existing system that uses a LegacyPrinter class with a method named printDocument() which we want to adapt into a new system that expects a Printer interface with a method named print(). We'll use the Adapter design pattern to make these two interfaces compatible.

class_diagram_of_adapter_design_pattern

Class Diagram

1. Target Interface (Printer)

The interface that the client code expects.

C++ `

// Target Interface class Printer { public: virtual void print() = 0; // Pure virtual function (abstract method) };

Java

/* Target Interface */ interface Printer { void print(); }

Python

""" Target Interface """ from abc import ABC, abstractmethod

class Printer(ABC): @abstractmethod def print(self): pass

JavaScript

// Target Interface class Printer { print() { throw new Error('Method not implemented.'); } }

`

2. Adaptee (LegacyPrinter)

The existing class with an incompatible interface.

C++ `

// Adaptee

class LegacyPrinter { public: void printDocument() { std::cout << "Legacy Printer is printing a document." << std::endl; } };

Java

/* Adaptee */

class LegacyPrinter { public void printDocument() { System.out.println("Legacy Printer is printing a document."); } }

Python

Adaptee

class LegacyPrinter: def print_document(self): print('Legacy Printer is printing a document.')

JavaScript

// Adaptee

class LegacyPrinter { printDocument() { console.log('Legacy Printer is printing a document.'); } }

`

3. Adapter (PrinterAdapter)

The class that adapts the LegacyPrinter to the Printer interface.

C++ `

// Adapter

class PrinterAdapter : public Printer { private: LegacyPrinter legacyPrinter;

public: void print() override { legacyPrinter.printDocument(); } };

Java

/* Adapter */

class PrinterAdapter implements Printer { private LegacyPrinter legacyPrinter;

public PrinterAdapter(LegacyPrinter legacyPrinter) {
    this.legacyPrinter = legacyPrinter;
}

@Override
public void print() {
    legacyPrinter.printDocument();
}

}

Python

Adapter

class PrinterAdapter(Printer): def init(self, legacy_printer): self.legacy_printer = legacy_printer

def print(self):
    self.legacy_printer.print_document()

JavaScript

// Adapter

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

print() {
    this.legacyPrinter.printDocument();
}

}

`

4. Client Code

The code that interacts with the Printer interface.

C++ `

// Client Code

void clientCode(Printer& printer) { printer.print(); }

Java

/* Client Code */ interface Printer { void print(); }

void clientCode(Printer printer) { printer.print(); }

Python

Client Code

from abc import ABC, abstractmethod

class Printer(ABC): @abstractmethod def print(self): pass

def clientCode(printer): printer.print()

JavaScript

// Client Code function clientCode(printer) { printer.print(); }

`

Complete Code for the above example:

C++ `

// Adapter Design Pattern Example Code

#include

// Target Interface class Printer { public: virtual void print() = 0; };

// Adaptee class LegacyPrinter { public: void printDocument() { std::cout << "Legacy Printer is printing a document." << std::endl; } };

// Adapter class PrinterAdapter : public Printer { private: LegacyPrinter legacyPrinter;

public: void print() override { legacyPrinter.printDocument(); } };

// Client Code void clientCode(Printer& printer) { printer.print(); }

int main() { // Using the Adapter PrinterAdapter adapter; clientCode(adapter);

return 0;

}

Java

/* Adapter Design Pattern Example Code */

// Target Interface interface Printer { void print(); }

// Adaptee class LegacyPrinter { public void printDocument() { System.out.println("Legacy Printer is printing a document."); } }

// Adapter class PrinterAdapter implements Printer { private LegacyPrinter legacyPrinter = new LegacyPrinter();

@Override
public void print() {
    legacyPrinter.printDocument();
}

}

// Client Code public class Client { public static void clientCode(Printer printer) { printer.print(); }

public static void main(String[] args) {
    // Using the Adapter
    PrinterAdapter adapter = new PrinterAdapter();
    clientCode(adapter);
}

}

Python

''' Adapter Design Pattern Example Code '''

Target Interface

from abc import ABC, abstractmethod

class Printer(ABC): @abstractmethod def print(self): pass

Adaptee

class LegacyPrinter: def print_document(self): print('Legacy Printer is printing a document.')

Adapter

class PrinterAdapter(Printer): def init(self): self.legacy_printer = LegacyPrinter()

def print(self):
    self.legacy_printer.print_document()

Client Code

def client_code(printer): printer.print()

if name == 'main': # Using the Adapter adapter = PrinterAdapter() client_code(adapter)

JavaScript

/* Adapter Design Pattern Example Code */

// Target Interface const Printer = { print: function() { throw new Error('print method must be implemented!'); } };

// Adaptee class LegacyPrinter { printDocument() { console.log('Legacy Printer is printing a document.'); } }

// Adapter class PrinterAdapter { constructor() { this.legacyPrinter = new LegacyPrinter(); }

print() {
    this.legacyPrinter.printDocument();
}

}

// Client Code class Client { static clientCode(printer) { printer.print(); }

static main() {
    // Using the Adapter
    const adapter = new PrinterAdapter();
    this.clientCode(adapter);
}

}

// Running the client code Client.main();

`

Output

Legacy Printer is printing a document.

Advantages

The pros of Adapter Design Pattern:

Disadvantages

The cons of Adapter Design Pattern: