![Decorator pattern diagram](https://upload.wikimedia.org/wikipedia/commons/thumb/e/e9/Decorator_UML_class_diagram.svg/400px-Decorator_UML_class_diagram.svg.png)

It's already known that, more than knowing many kind of patterns, is knowing when to apply them. We should not try to apply patterns before knowing your problem, this is not how they are meant to be used. They are tools for specific situations. Don't think about them before: understand your problem, look at your messy code (because it will be at first, you know it), then try to figure if a pattern is applicable.

To finish my series about Decorator Pattern, I thought it would be useful to give some examples of when we can apply it with good results. Also, I will be showing them in real-case scenarios, that I used in my working experience until now.

Feature toggling

Imagine you have a new feature that, when enabled, should override the old one. This is a perfect scenario for composition through decoration. When done, all you need to do is change the composition root:

public interface IFeature
{
    void Run();
}

public interface IConfigurationGetter
{
    T GetConfiguration(string key);
}

public class OldFeature : IFeature
{
    public void Run()
    {
        // Old feature algorithm runs here
    }
}

class NewFeature : IFeature
{
    public void Run()
    {
        // New feature algorithm runs here
    }
}

public class RoutedFeature : IFeature
{
    private const string ConfigurationKey = "NewFeatureEnabled";

    public readonly IConfigurationGetter ConfigurationGetter;
    public readonly IFeature OldFeature;
    public readonly IFeature NewFeature;

    public RoutedFeature(
        IConfigurationGetter configurationGetter,
        IFeature oldFeature,
        IFeature newFeature)
    {
        ConfigurationGetter = configurationGetter
            ?? throw new ArgumentNullException(nameof(configurationGetter));

        OldFeature = oldFeature
            ?? throw new ArgumentNullException(nameof(oldFeature));

        NewFeature = newFeature
            ?? throw new ArgumentNullException(nameof(newFeature));
    }

    public void Run()
    {
        if (IsNewFeatureEnabled())
            NewFeature.Run();
        else
            OldFeature.Run();
    }

    private bool IsNewFeatureEnabled()
    {
        return ConfigurationGetter.GetConfiguration(ConfigurationKey);
    }

Alternative to inheritance

One of the principal problems with inheritance is that many programmers think of problems first as potential inheritance solutions. As a concrete concept that is quick to learn (often one of the first for new OO developers), many latch onto that and never really grow much as system modelers. If you everything in your system is hierarchically modeled by inheritance and also code being reused by inheritance, the results can be disastrous. Code gets more coupled instead of the opposite.
What I am trying to say here is to ponder inheritance after composition, accordingly to points in GoF Design Patterns book:

  1. Favor composition over inheritance (p. 20);
  2. Object composition lets you change the behavior being composed at run-time, but it also requires indirection and can be less efficient (p. 22);
  3. On the other hand, heavy use of object composition can make designs harder to understand (p. 25).

So, inheritance and composition both have good and bad sides. Try to apply composition first, if it does not become as good as inheritance and by inheritance you dont couple your code, then choose the latter.

The biggest thing gained when switching from inheritance to composition is a flee of a bad combination practice. Imagine you have a class extension by inheritance, that provides an extra functionality over the base one. Then you come up with anoter class that extends another functionality. Then, eventually you want one that combines the two, and here is where you get a problem: you have to create another class that combines the two somehow, and you break inheritance chain.

public class Feature
{
    public virtual void Run()
    {
        // Base feature algorithm here
    }
}

public class ExtendedFeature1 : Feature
{
    public override void Run()
    {
        // Extended feature algorithm here
        base.Run();
    }
}

public class ExtendedFeature2 : Feature
{
    public override void Run()
    {
        // Extended feature algorithm here
        base.Run();
    }
}

// How to combine Feature1 and Feature2 through inheritance? We can't make a
// CombinedFeature that inherits from Feature while receiving both as 
// dependencies, because both ExtendedFeature1 and ExtendedFeature2 already
// calls the base Run method. That would make the base run method being
// called twice, and would not work. Conclusion: inheritance allows we to
// extend features, but only in a one side way: we can't choose two extended
// features and compose them into one.
public class CombinedFeature : Feature
{

}

By using decorator, you still play with lego: you don't need to implement another class to combine them both, instead, you compose them at your composition root.

public interface IFeature
{
    void Run();
}

public class Feature : IFeature
{
    public virtual void Run()
    {
        // Base feature algorithm here
    }
}

public class ExtendedFeature1 : IFeature
{
    public readonly IFeature Inner;

    public ExtendedFeature1(IFeature inner)
    {
        Inner = inner ?? throw new ArgumentNullException(nameof(inner));
    }

    public void Run()
    {
        // Extended feature algorithm here
        Inner.Run();
    }
}

public class ExtendedFeature2 : IFeature
{
    public readonly IFeature Inner;

    public ExtendedFeature2(IFeature inner)
    {
        Inner = inner ?? throw new ArgumentNullException(nameof(inner));
    }

    public void Run()
    {
        // Extended feature algorithm here
        Inner.Run();
    }
}

// With decoration of features, we don't need a third combined implementation
// of the two features. We just compose them at our composition root!
// ExtendedFeature2 will do its extended behavior, and call ExtendedFeature1,
// wich in turn does its own extended behavior, and call the base feature
// behavior. We made a good trade from inheritance to delegation.
public class CompositionRoot
{
    public IFeature GetCombinedFeature()
    {
        return new ExtendedFeature2(new ExtendedFeature1(new Feature()));
    }
}

Also, I don't need to mention again about unit testability and Single Responsiblity Principle, do I? You don't have them at our inheritance case. Both ExtendedFeature1 and ExtendedFeature2 will have a strong connection to the base Feature class, while here we don't have it.

Alongside inheritance

Let's go back to our last composition case. We can use inheritance here, alongside our composition through decoration, and that is a case that I would totally approve. See that we have a repeated code here? Both decorators receive an IFeature to be decorated, and we do good patterns by checking if they are not null references. We can do an abstract implementation of a Decorator and avoid repeating this code:

public abstract class FeatureDecorator : IFeature
{
    public readonly IFeature Inner;

    public FeatureDecorator(IFeature inner)
    {
        Inner = inner ?? throw new ArgumentNullException(nameof(inner));
    }

    public abstract void Run();
}

public class ExtendedFeature1 : FeatureDecorator
{
    public ExtendedFeature1(IFeature inner) : base(inner)
    {
    }

    public override void Run()
    {
        // Extended feature algorithm here
        Inner.Run();
    }
}

public class ExtendedFeature2 : FeatureDecorator
{
    public ExtendedFeature2(IFeature inner) : base(inner)
    {
    }

    public override void Run()
    {
        // Extended feature algorithm here
        Inner.Run();
    }
}

Combining composition and inheritance this way, we can reach a more compact code, and still maintain all the principles of SOLID and OO that we want to preserve.

Other cases that should make you think about it

Knowing those principles before, all you have to do now is associate them in cases of necessity. In my experience, all of those listed below makes me immediately think about using this pattern:

  • Verbose logging: By default, verbose logging should be toggable. Wich brings us to the ToggleFeature case.
  • Synchronization: Decorate a basic functionality with the sincronization process: after calling the base one, do the other.
  • Read-only access: You can control whether or not to give access to a feature through decoration of it. Before calling the base, verify if you should do it by doing the security check.
  • Remoting (proxy pattern): You can reach a proxy pattern with decoration too.
  • Profiling: Same thing as verbose logging.
  • Security: Decorate a base message sender class and encrypts the message being sent by it. Simple, and composable.
  • Combining with other patterns: It's common to use combinations of Decorator and Composite patterns. We have rarer cases of other combinations, like Decoraptor Pattern.