Decorating a component that doesn't want to be decorated

Akos Nagy
Feb 22, 2019

Decorator is one of the most useful OO design patterns out there. It's basically a holy grail of helping you stay S.O.L.I.D.: it lets you keep the responsibilities to a minimum in a component, while also being probably one of the best examples of the open/closed principle. As I always say to students, if you only learn one, this should be it.

However, applying a decorator is not always easy and in some cases you have to refactor your code a bit. Of course if you kept the single most important rule of OO (program against abractions, not implementations), you should be fine. But even then, there are smaller scale decisions that might affect how (or if) this design pattern can be implemented.

The basic setup: decorating a protected method

So let's say you have something like this:

public class Component
{
   public void DoSomethingAwesome()
   {
      Console.WriteLine("Less awesome");
      DoAnAwesomeStep();
      Console.WriteLine("Less awesome");
   }
   protected virtual void DoAnAwesomeStep()
   {
      Console.WriteLine("This is awesome");
   }
}

public class IngestorComponent
{
   public static void UseSomethingAwesome(Component awesomeService)
   {
     awesomeService.DoSomethingAwesome();
   }
}

So this is your current solution and you want to add decorators that can extend the functionality of the protected method (notice that the public method that uses the proctected cannot be decorated, because it does not support polymorphism; but even if you could, decorating that would have an entirely different effect).

Usually, a decorator for the component would look like this:

public class ComponentDecorator : Component
{
   private readonly Component decoratee;
   public ComponentDecorator(Component decoratee)
   {
     this.decoratee = decoratee;
   }
   
   protected override void DoAnAwesomeStep()
   {
      Console.WriteLine("This is some extra awesomeness before the original");
      this.decoratee.DoAnAwesomeStep();
   }
}

But this doesn't work for protected members. It is true that you can access protected members in the descendant class, but only through the base reference (i.e. access the objects own protected members). So the usual decorator pattern does not work here.

Implementing decoration with adapters

So what can you do? Here's a pattern that might help. Note that I do not claim that I have inveted this pattern. Patterns are good because they emerge on their own, so I guess this has to be out there already, I just couldn't find the right keywords for my Google-search.

So the first step is to (unfortunately) replicate the interface to be decorated with an actual language interface:

public interface IAwesomeStepper
{
  void DoAwesomeStep();
}

Second, provide a default implementation for this interface that is basically a class adapter for the original component:

public class DefaultComponent : Component, IAwesomeStepper
{
   public void DoAwesomeStep() => base.DoAnAwesomeStep();
}

Now, you can use this DefaultComponent in place of a Component dependency and you can access all the functionality as well in the descendant class.

And now, this new interface can be decorated like this:

public class ComponentDecorator : IAwesomeStepper
{
   private readonly IAwesomeStepper decoratee;
   
   public ComponentDecorator(IAwesomeStepper decoratee)
   {
     this.decoratee = decoratee;
   }
   
   public void DoAwesomeStep()
   {
     // added your decorating features here
     decoratee.DoAwesomeStep();
   }
}

So now you have access to the functionality of the original component through the DefaultComponent implementation, and since that also implements an additional interface, decoration can be done through that.

Of course, this ComponentDecorator is now incompatible with the original Component dependency. So what do you do when you have a component that's incompatible with your current system-interfaces? You create an adapter, again. This time, an object adapter suits the situation the best:

public class ComponentDecoratorAdapter : Component
{
   // If you introduce a decoratorbase class, you could use that here
   private readonly IAwesomeStepper awesomeStepper;
   
   public ComponentDecoratorAdapter(IAwesomeStepper awesomeStepper)
   {
     this.awesomeStepper = awesomeStepper;
   }
   
   protected override void DoAnAwesomeStep() => awesomeStepper.DoAwesomeStep();   
}

So how would this work? Let's see

DefaultComponent dc = new DefaultComponent();
ComponentDecorator cd = new ComponentDecorator(dc);
ComponentDecoratorAdapter cda = new ComponentDecoratorAdapter(cd);
IngestorComponent.UseSomethingAwesome(cda);

Whenever the last method is called, it calls into the adapters public method, which in turn, calls into the overloaded method in the adapter. The overloaded method in the adapter simply calls the wrapped objects method. Since the wrapped object is a decorator, the extra functionality is called and then the decorated component's same method is called. This is the DefaultComponent, whose method in turn, simply calls into the base class funtionality.

Not to brag, but this is kind of awesome :) Stay tuned for the description of a real-life problem where I faced this challenge and the implementation using this method.

Akos Nagy
Posted in Software design