Introduction to the Adapter Pattern in Python

Introduction to the Adapter Pattern

Welcome to our journey through Structural Patterns! Structural Patterns help manage object compositions and relationships, aiding in the creation of more scalable and flexible systems. One foundational structural pattern is the Adapter Pattern, which focuses on enabling two incompatible interfaces to work together seamlessly. Imagine you have a European plug that you need to use with a U.S. socket. They are inherently incompatible, but through an adapter, you can bridge this gap. Similarly, in software design, you often encounter situations where you need to integrate classes with incompatible interfaces. The Adapter Pattern provides a way to achieve this integration.

Core Components of the Adapter Pattern

The key components of the Adapter Pattern include the Target Interface, the Adaptee, and the Adapter. The Target Interface is the interface expected by the client. In our example, this would be USPlug. The Adaptee is the existing interface that needs adapting, which in our case, is EuropeanPlug. The Adapter is the class that bridges the gap between the Target Interface and the Adaptee.

Step 1: Define the Adaptee

We start by defining the Adaptee, which in our case is the European plug. Here’s the initial code for the EuropeanPlug class:

class EuropeanPlug:
    def connect(self):
        print("European plug connected.")

The EuropeanPlug class has a connect method that prints a string indicating that the plug is connected. This is the starting point of our implementation.

Step 2: Define the Target Interface

Next, we define the Target Interface that our client will interact with. In our example, this is an abstract class named USPlug with an abstract connect method:

from abc import ABC, abstractmethod

class USPlug(ABC):
    @abstractmethod
    def connect(self):
        pass

The USPlug class inherits from ABC (Abstract Base Class) and its connect method is an abstract method. This defines the interface expected by the client.

Step 3: Create the Adapter

Now, we need to create the Adapter that will bridge the EuropeanPlug with the USPlug interface. Here’s how we define the Adapter class:

class Adapter(USPlug):
    def __init__(self, european_plug):
        self.european_plug = european_plug

    def connect(self):
        self.european_plug.connect()

The Adapter class inherits from the USPlug abstract base class, which means it is of the type USPlug. By inheriting from USPlug, the Adapter class is required to implement the connect method defined in the USPlug interface. This guarantees that the Adapter conforms to the expected interface, allowing it to be used wherever a USPlug is required. The Adapter class takes an instance of EuropeanPlug and implements the connect method in such a way that it calls the connect method of the EuropeanPlug instance. This effectively adapts the European plug to the U.S. plug interface.

Sign up

Join the 1M+ learners on CodeSignal

Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal