Design Pattern

Adapter Design Pattern (“Wrapper”)

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

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

Introduced briefly in CS247, but mainly teacher focused 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 the 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

Some super simple example (you’re just renaming the functions basically, remapping the interfaces)

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;
}
 

CS138: Stack as a Vector

You actually initially saw the adapter pattern in this class, where you saw that a Stack could be easily implemented by a vector! However, you hide the implementation details, i.e. you do Information hiding, which is Encapsulation!

An adapter is sometimes also called a wrapper class.

Implementing a stack as a vector:

#include <iostream>
#include <vector>
 
class Stack {
std::vector<int> stackVec;
public:
  void push(int val) {
    stackVec.push_back(val);
  }
 
  void pop() {
    if (!isEmpty()) {
      stackVec.pop_back();
    }
  }
 
  int top() {
    if (!isEmpty()) {
      return stackVec.back();
    }
    return -1; // Error value
  }
 
  bool isEmpty() {
    return stackVec.empty();
  }
};
 

What is the difference between an Interface Class and a wrapper class?

An interface class in C++ serves as a blueprint for other classes. It declares methods without defining their implementation. This is different from what we are trying to achieve in a wrapper class, since we CAN directly use the wrapper class.