Adapter Pattern

Updated Nov 23, 2025

Adapter Pattern

Intent:

Allows incompatible interfaces to work together by wrapping an object with an adapter that translates between the two interfaces.

When to Use:

When you need to use an existing class, but its interface doesn't match what you need. Instead of modifying the existing class, you create an adapter to make it compatible.

Key Characteristics:

  • Acts as a bridge between two incompatible interfaces
  • Wraps an existing class to make it compatible with another interface
  • Allows classes to work together that couldn't otherwise
  • Doesn't modify existing code

Think of it like a travel adapter - your phone charger has a US plug, but you're in India. You use an adapter to make it work with Indian sockets without changing your charger.


🏦 Example: Bank Payment Integration

Let's say we're building an e-commerce application that needs to process payments through different banks. HDFC Bank and ICICI Bank have different payment interfaces. We need to make them work with our unified payment system.

Step 1: Define Target Interface (What We Need)

# payment_interface.py from abc import ABC, abstractmethod class PaymentProcessor(ABC): @abstractmethod def process_payment(self, amount, account_number): pass # All banks must implement this

Step 2: HDFC Bank (Existing Class - Incompatible Interface)

# hdfc_bank.py class HDFCBank: def __init__(self, account_number): self.account_number = account_number def make_payment(self, amount): """HDFC uses 'make_payment' method with different signature""" print(f"[HDFC Logo] Processing payment of ₹{amount} from account {self.account_number}") print(f"[HDFC Logo] Payment successful via HDFC Bank") return True

Step 3: ICICI Bank (Existing Class - Incompatible Interface)

# icici_bank.py class ICICIBank: def __init__(self, account_number): self.account_number = account_number def transfer_money(self, amount): """ICICI uses 'transfer_money' method with different signature""" print(f"[ICICI Logo] Transferring ₹{amount} from account {self.account_number}") print(f"[ICICI Logo] Transfer completed via ICICI Bank") return True

Step 4: Create HDFC Adapter

# hdfc_adapter.py from payment_interface import PaymentProcessor from hdfc_bank import HDFCBank class HDFCAdapter(PaymentProcessor): def __init__(self, account_number): self.hdfc_bank = HDFCBank(account_number) def process_payment(self, amount, account_number): """Adapts HDFC's interface to our PaymentProcessor interface""" # HDFC uses make_payment, we adapt it to process_payment return self.hdfc_bank.make_payment(amount)

Step 5: Create ICICI Adapter

# icici_adapter.py from payment_interface import PaymentProcessor from icici_bank import ICICIBank class ICICIAdapter(PaymentProcessor): def __init__(self, account_number): self.icici_bank = ICICIBank(account_number) def process_payment(self, amount, account_number): """Adapts ICICI's interface to our PaymentProcessor interface""" # ICICI uses transfer_money, we adapt it to process_payment return self.icici_bank.transfer_money(amount)

Step 6: Use the Adapters (Client Code)

# main.py from payment_interface import PaymentProcessor from hdfc_adapter import HDFCAdapter from icici_adapter import ICICIAdapter def process_order_payment(payment_processor: PaymentProcessor, amount, account_number): """Unified payment processing - works with any bank via adapter""" print(f"\n=== Processing Payment ===") payment_processor.process_payment(amount, account_number) # Process payment through HDFC print("Order 1: Payment via HDFC Bank") hdfc_adapter = HDFCAdapter("HDFC123456") process_order_payment(hdfc_adapter, 5000, "HDFC123456") # Process payment through ICICI print("\nOrder 2: Payment via ICICI Bank") icici_adapter = ICICIAdapter("ICICI789012") process_order_payment(icici_adapter, 3000, "ICICI789012") # Both banks now work with the same interface!

Output:

Order 1: Payment via HDFC Bank

=== Processing Payment ===
[HDFC Logo] Processing payment of ₹5000 from account HDFC123456
[HDFC Logo] Payment successful via HDFC Bank

Order 2: Payment via ICICI Bank

=== Processing Payment ===
[ICICI Logo] Transferring ₹3000 from account ICICI789012
[ICICI Logo] Transfer completed via ICICI Bank

✅ Benefits

1. Compatibility:

  • Makes incompatible interfaces work together
  • No need to modify existing bank classes

2. Reusability:

  • Can use existing classes without changing them
  • Adapters can be reused across different parts of the application

3. Separation of Concerns:

  • Client code doesn't need to know about different bank interfaces
  • All complexity is handled by adapters

4. Flexibility:

  • Easy to add new banks - just create a new adapter
  • Existing code remains unchanged

🎯 Key Points

  • Adapter acts as a bridge between incompatible interfaces
  • Wraps existing class to make it compatible
  • Client code works with unified interface
  • Existing classes don't need to be modified
  • Easy to add new adapters for new banks or services

🌟 Quick Summary

  • Problem: Need to use existing classes with incompatible interfaces
  • Solution: Create adapters that translate between interfaces
  • Benefit: Makes incompatible classes work together without modifying them
  • Example: Different banks (HDFC, ICICI) with different payment methods unified through adapters

🎉 End

The Adapter Pattern helps you integrate existing code with new systems. It's perfect when you need to make incompatible interfaces work together!