Back to Overview

Adapter Pattern

The Adapter Pattern converts the interface of a class into another interface that clients expect. It allows classes to work together that couldn't otherwise because of incompatible interfaces.

Think of it like a power adapter that lets you plug a device from one country into an outlet in another country - it changes the interface but preserves the underlying functionality.

Problem

Imagine you have an existing system with a well-defined interface. Now you want to use another library or system that has a different interface. You can't change either system's code, but you need them to work together.

Client Target Interface Adapter Adaptee

Components

Implementation Example

Let's look at a real-world example of the Adapter pattern: adapting a legacy payment system to work with a new e-commerce platform.

// Target Interface: What our e-commerce system expects
class ModernPaymentProcessor {
    processPayment(amount) {
        // Process the payment
    }
}

// Adaptee: Legacy payment system with a different interface
class LegacyPaymentSystem {
    constructor() {
        this.status = 'initialized';
    }
    
    initialize() {
        this.status = 'ready';
        return true;
    }
    
    makePayment(dollars, cents) {
        if (this.status !== 'ready') {
            return false;
        }
        console.log(`Legacy payment processed: $${dollars}.${cents}`);
        return true;
    }
    
    shutdown() {
        this.status = 'closed';
    }
}

// Adapter: Makes LegacyPaymentSystem work with our expected interface
class PaymentSystemAdapter extends ModernPaymentProcessor {
    constructor(legacySystem) {
        super();
        this.legacySystem = legacySystem;
        this.legacySystem.initialize();
    }
    
    processPayment(amount) {
        // Split the amount into dollars and cents for the legacy system
        const dollars = Math.floor(amount);
        const cents = Math.round((amount - dollars) * 100);
        
        // Call the adaptee using its interface
        const result = this.legacySystem.makePayment(dollars, cents);
        
        if (!result) {
            throw new Error('Payment failed');
        }
        
        return {
            success: true,
            amount: amount,
            timestamp: new Date()
        };
    }
}

Interactive Demo: Payment System Adapter

Try processing payments using the adapter pattern, which connects our new system to the legacy payment processor.

// Payment results will appear here

When to Use

Benefits

Real-World Uses