Adapter Design Pattern

The adapter/wrapper pattern is a software design pattern that allows the interface of an existing class to be used as another interface.

Adapter is a structural design pattern that allows objects with incompatible interfaces to collaborate.

  • Often used to make existing classes work with others without modifying their source code

Introduced in CS247 - Software Engineering Principles, but he doesn’t focus too much on it. More focus on Interface Segregation Principle.

When to use Adapter Pattern

We already have one interface, and we want to use these classes with a client that expects a different interface.

So you wrap things using only what you truly want.

Steps

  1. Define API you really want! For stack , this is push, pop, etc., not emplace_back, pop_back that would be defined in a Deque.
  2. Instantiate (don’t inherit!) an object from the “workhorse” class that will do the actual heavy lifting, probably as a private data member
  3. Define the appropriate operations as fairly trivial “wrapper” operations using the workhorse class’ methods
    This is also called forwarding or delegating

Resource: https://refactoring.guru/design-patterns/adapter

Very simple example:

class OldMusicPlayer {
public:
    void playOldFormat() {
        // Playing old format
    }
};
 
class Adapter {
private:
    OldMusicPlayer oldPlayer;
public:
    void play() {
        oldPlayer.playOldFormat();
    }
};
 
int main() {
    Adapter player;
    player.play(); // Plays using old format
    return 0;
}

Taken from https://www.dofactory.com/net/adapter-design-pattern.

The client (maybe an external library) expects to use a class that has a “Request” method. We, however, programmed our method with the name “specificRequest”, and this is used frequently throughout our code base. It would be a band-aid solution to change “specificRequest” to “request” everywhere throughout our code - and that might not even fix things! We might have a second external  library that relies on the method being called “specificRequest”, and so changing it to “request” everywhere would make our class work with the first library, but not the second.

If we need to satisfy two clients at once: one who expects a method called “request”, and the other who expects a method called “specificRequest” - then we can pick one to support naturally (in this case, specificRequest”, and one to support via an Adapter - which is just a wrapper class, that provides a method called “request”, which calls the original method “specificRequest”

??? In summary, the Adapter Design Pattern is a great way to bridge the gap between different interfaces without the need for significant changes to your existing code. It’s a flexible and powerful tool for integrating components that might have incompatible interfaces while adhering to the principles of SOLID design.