Skip to content

Design Patterns: Decorator

Kaisinel edited this page Feb 13, 2021 · 7 revisions

Decorator

Problem

Have you ever had a need to stack behaviour to an existing implementation? For example, imagine there are 3 behaviours: A, B, C with the same definitions. You need to do a mix of them: either A or B or C or AB or AC or BC or ABC. In fact, the order itself matters too.We might seem like a nice solution to this problem. We could have a class C, inheriting class B, inheriting class A, overriding the same method and adding behaviour on top. But, when we need to make a slightly different combo (A with C, but not with B)- we will fail miserably with inheritance because we will end up with dozens of classes.

But there is another, better way.

Decorator

Decorator is a structural design pattern which aims to add additional behaviour to an existing class without modifying it. The most basic decorator looks like this:

// To be decorated.
public interface ILogger
{
  void Log(string text);
}

public class ConsoleLogger : ILogger
{
  public void Log()
  {
    // Log to console.
  }
}

// Decorator
public class LoggerToDb: ILogger
{
  // Decoratee = original interface implementations + other decorators.
  private readonly ILogger _logger;
  public LoggerToDb(ILogger logger)
  {
    _logger = logger;
  }

  public void Log(string text)
  {
    _logger.Log(text);
    // Order in this case doesn't matter.
    LogToDb(text);
  }

  private void LogToDb(string text)
  {
    // log to db.
  }
}