0
0
LldComparisonIntermediate · 4 min read

Adapter vs Decorator Pattern: Key Differences and Usage

The Adapter pattern changes an object's interface to match what a client expects, enabling incompatible interfaces to work together. The Decorator pattern adds new behavior to an object dynamically without changing its interface, enhancing functionality transparently.
⚖️

Quick Comparison

This table summarizes the main differences between the Adapter and Decorator patterns.

AspectAdapter PatternDecorator Pattern
PurposeConvert interface of one class to another expected by clientAdd new behavior or responsibilities to an object dynamically
Interface ChangeYes, adapts to a different interfaceNo, keeps the original interface intact
FocusCompatibility between different interfacesEnhancing or extending functionality
Usage ScenarioWhen existing class interface is incompatibleWhen you want to add features without subclassing
Object WrappingWraps an object to change its interfaceWraps an object to add behavior
Effect on ClientClient uses adapted interfaceClient uses same interface with added features
⚖️

Key Differences

The Adapter pattern acts like a translator between two incompatible interfaces. It wraps an existing object and exposes a new interface that the client expects. This pattern is useful when you want to reuse a class but its interface does not match what your code needs.

In contrast, the Decorator pattern wraps an object to add new behaviors or responsibilities without changing its interface. It allows you to extend functionality dynamically and transparently, meaning the client still interacts with the object as usual but with enhanced features.

While both patterns use wrapping, Adapter changes the interface to achieve compatibility, whereas Decorator preserves the interface and focuses on adding capabilities.

⚖️

Code Comparison

java
interface Target {
    void request();
}

// Existing incompatible class
class Adaptee {
    void specificRequest() {
        System.out.println("Adaptee specific request");
    }
}

// Adapter makes Adaptee compatible with Target
class Adapter implements Target {
    private Adaptee adaptee;

    Adapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }

    public void request() {
        adaptee.specificRequest();
    }
}

public class Main {
    public static void main(String[] args) {
        Adaptee adaptee = new Adaptee();
        Target adapter = new Adapter(adaptee);
        adapter.request();
    }
}
Output
Adaptee specific request
↔️

Decorator Equivalent

java
interface Component {
    void operation();
}

// Concrete component
class ConcreteComponent implements Component {
    public void operation() {
        System.out.println("ConcreteComponent operation");
    }
}

// Decorator adds behavior
class Decorator implements Component {
    protected Component component;

    Decorator(Component component) {
        this.component = component;
    }

    public void operation() {
        component.operation();
        addedBehavior();
    }

    void addedBehavior() {
        System.out.println("Decorator added behavior");
    }
}

public class Main {
    public static void main(String[] args) {
        Component component = new ConcreteComponent();
        Component decorated = new Decorator(component);
        decorated.operation();
    }
}
Output
ConcreteComponent operation Decorator added behavior
🎯

When to Use Which

Choose Adapter when you have an existing class with an interface that does not match what your client code expects, and you want to make it compatible without changing the original class.

Choose Decorator when you want to add new features or responsibilities to objects dynamically and transparently, without altering their interface or using subclassing.

In short, use Adapter for interface compatibility and Decorator for flexible behavior extension.

Key Takeaways

Adapter changes an object's interface to match client expectations.
Decorator adds new behavior without changing the object's interface.
Adapter solves incompatibility between interfaces; Decorator enhances functionality.
Use Adapter to integrate legacy or third-party code with different interfaces.
Use Decorator to add features dynamically without subclassing.