What are the differences between Decorator, Wrapper and Adapter patterns?

12,652

Solution 1

In theory they are the same, it's the intent that differentiates one pattern from the other:

Decorator:

Allows objects to be composed/add capabilities by wrapping them with a class with the same interface

Adapter:

Allows you to wrap an object without a known interface implementation so it adheres to an interface. The point is to "translate" one interface into another.

Wrapper:

Never heard of this as a design pattern, but I suppose it's just a common name for the above

The example you specify I would categorize as a decorator: The CacheRepository decorates an IRepository to add caching capabilities.

Solution 2

A programmer may write a class A with a focus on holding an object of another class B. Class A would be referred to as a wrapper for class B. Why have class A wrap around class B? To decorate or adapt it. Decorators and adapters are wrappers.


Imagine that class A is written such that it implements the interface of class B by calling the methods of its class B object. It could then be used in place of class B. There's no point in this other than the fact that it gives the programmer the opportunity to add some code before or after the calls to the methods of the class B object. This version of class A would be called a decorator of class B. Decorators leave the interface the same while adding some behavior.

interface ICatInterface {
  public void wakeUp();
}

class Cat implements ICatInterface {
  public void wakeUp() {
    System.out.println("I came. I saw. I napped.");
  }
}

class YogaCat implements ICatInterface {

  private ICatInterface cat;

  public YogaCat(ICatInterface cat) {
    this.cat = cat;
  }

  public void wakeUp() {
    System.out.println("[Stretch]"); // <- This is the decoration.
    cat.wakeUp();
  }
}

See this example of a more complicated way to use this pattern for composing objects of differing behavior during runtime.


Imagine now that class A is written such that it implements some interface C, but is implemented mostly via calls to the methods of its class B object. This is a way to translate the methods available in class B to interface C. This version of class A would be called an adapter of class B. It's like when you want to charge your phone. There are adapters that go from wall or car power source to USB port. Adapters change the interface to some other interface, but don't necessarily add any behaviors.

interface TakeDirectionsInterface {
  public void turnLeft();
  public void turnRight();
  public void go();
  public void stop();
}

class Driver {
  public enum TurnDirection
  { 
    CLOCKWISE, COUNTERCLOCKWISE;
  }

  public enum FootPedal
  { 
    ACCELERATOR, BRAKE, CLUTCH;
  }

  public void turnSteeringWheel(TurnDirection direction) {
    System.out.println("Turning the steering wheel " + direction.toString() + ".");
  }

  public void pressPedal(FootPedal pedal) {
    System.out.println("Pressing the " + pedal.toString() + "pedal.");
  }
}

class DriverAdapter implements TakeDirectionsInterface {

  private Driver driver;

  public DriverAdapter(Driver driver) {
    this.driver = driver;
  }

  public void turnLeft(){
    driver.turnSteeringWheel(Driver.TurnDirection.COUNTERCLOCKWISE);
  }

  public void turnRight(){
    driver.turnSteeringWheel(Driver.TurnDirection.CLOCKWISE);
  }

  public void go(){
    driver.pressPedal(Driver.FootPedal.ACCELERATOR);
  }

  public void stop(){
    driver.pressPedal(Driver.FootPedal.BRAKE);
  }
}

Share:
12,652

Related videos on Youtube

Zoltán Tamási
Author by

Zoltán Tamási

Recently focusing on Cloud-based architectures and software design. I mostly work with C#, TypeScript, JavaScript, HTML/CSS. I develop large ASP.NET WebApi/MVC web applications, and rich HTML5/TypeScript web clients using mostly today's technologies. I like hanging out here in my free time.

Updated on June 04, 2022

Comments

  • Zoltán Tamási
    Zoltán Tamási almost 2 years

    I feel like I've been using these pattern families quite many times, however, for me it's hard to see the differences as their definitions are quite similar. Basicaly it seems like all of them is about wrapping another object or objects to extend or wrap their behavior with extra stuff.

    For a quick example implementing a caching mechanism over a repository pattern seems to be this situation. Here is a quick sample C# code I would probably start with.

    public interface IRepository {
      IEnumerable<T> GetItems<T>();
    }
    
    public class EntityFrameworkRepository : IRepository {
      ...
    }
    
    public class CachedRepository : IRepository {
    
      private IRepository _repository;
      private ICacheProvider _cache;
    
      public CachedRepository(IRepository repository, ICacheProvider cache) {
        this._repository = repository;
        this._cache = cache;
      }
    
      public IEnumerable<T> GetItems<T>() {
        ...
      }
    }
    

    Which one of these patterns apply to this situation for example? Could anyone clarify briefly the differences in theory and in practice?

  • lexicore
    lexicore over 7 years
    Okay, I'm deleting my answer. :)
  • Zoltán Tamási
    Zoltán Tamási over 7 years
    The source of my confusion was "wrapper" as a separate pattern, which I've definitely read somewhere if I remember correctly. In the meantime another person confirmed that "wrapper" is rather a coding technique, which allows you to implement for example the decorator pattern. Thank you both for the clarification.
  • Kenneth
    Kenneth over 7 years
    Good stuff! I've stolen a bit from @lexicore answer on the adapter for future visitors.