Abstract
This article is a tutorial on the Decorator Pattern in C#. First, we show the Classic Decorator pattern, which is described in the literature and in GoF books. Then, we show 2 alternative versions that can be viewed as “modern-C#-enabled” versions of the pattern. The intended audience is Intermediate C# programmers and above.
Introduction
The decorator Pattern is one fascinating and very popular pattern. The pattern has the purpose of adding additional functionality to an existing object dynamically. Decorators provide an alternative to subclassing for extending functionality. While it is possible to add functionality to a whole class of objects by subclassing an object’s class, the Decorator pattern aims to add functionality to just a single object and leave other objects of that class unchanged.
It is sometimes commented that, by enhancing the existing type without modifying the original type, the pattern follows the Open-Close Principle.
What is very interesting is that the pattern achieves its goal by doing things the wrong way, against OO recommendations.
Composition vs. Inheritance
How to Choose?
A typical question in OOA/OOD courses is, for a given class/object A, when creating a new class/object B that is going to reuse class/object A, how and based on what criteria to choose between Composition and Inheritance? Recommendations are usually given: If you plan to reuse the Public interface of an existing class A, use Inheritance. If you plan to reuse just the functionality of an existing class A, go for Composition.
So, Decorator Pattern is doing exactly the opposite. It plans to reuse the Public Interface of an existing class but goes for Composition. That decision has some consequences regarding problems with extending the Public Interface, as we will see later.
Classic Decorator Pattern Version 1
Classic Decorator is a version of the pattern that was offered in the GoF book and is often mentioned in literature. Typically, you would have some interface IComponent abstracting some real class ComponentA. Our wish is to replace the object of class ComponentA with some object that will provide more/enhanced functionality, let’s call it DecoratorB, that implements the same interface IComponent. What we want it to replace
IComponent comp = new ComponentA();
With
IComponent comp = new DecoratorB(/*--some parameters--*/);
Where DecoratorB “improves” object ComponentA in a certain way.
In this pattern, DecoratorB goes for composition, it adds ComponentA as its component and reimplements interface IComponent from scratch, sometimes just passing methods calls to ComponentA methods.
So, let us assume we have this IComponent interface and ComponentA class implementations.
public interface IComponent //(1)
{
string StateI { get; set; } //(2)
string MethodI1(bool print = true); //(3)
}
public class ComponentA : IComponent //(4)
{
public string StateI { get; set; } //(5)
public string StateA { get; set; } //(6)
public ComponentA() //(7)
{ }
public string MethodI1(bool print = true) //(8)
{
string text = "ComponentA.MethodI1";
if (print) Console.WriteLine(text);
return text;
}
public string MethodA1() //(9)
{
string text = "ComponentA.MethodA1";
Console.WriteLine(text);
return text;
}
}
If you look at the IComponent interface, you see it exposes publicly one property (2) and one method (3).
Class ComponentA is our core component/functionality class. You can see that, of course, it implements the public interface of ICompnent (5), (8), but in addition, it has some additions to the class public interface at (6) and (9). When accessing class through interface IComponent, we are, of course, limited to properties/methods exposed by that interface, meaning that property (6) and method (9) will not be accessible.
Typical usage of the above classes would look like this.
Console.WriteLine("IComponent================================");
IComponent I = new ComponentA(); //(20)
I.StateI = "123";
//I.StateA = "123"; //not possible
string tmpI1 = I.MethodI1(); //(21)
//string tmpI2 = I.MethodA1(); //not possible //(22)
Console.WriteLine("ComponentA================================");
ComponentA A = new ComponentA(); //(23)
A.StateI = "123";
A.StateA = "123";
string tmpA1 = A.MethodI1();
string tmpA2 = A.MethodA1();
Now, let us see what a sample decorator class would look like.
public class DecoratorB : IComponent //(10)
{
public string StateI { get; set; } //(11)
public string StateB { get; set; } //(12)
private IComponent component = null; //(13)
public DecoratorB(IComponent comp) //(14)
{
component = comp;
}
public string MethodI1(bool print = true) //(15)
{
string baseTmp = component.MethodI1(false);
string text = baseTmp + " " + "DecoratorB.MethodI1";
if (print) Console.WriteLine(text);
return (text);
}
public string MethodB1() //(16)
{
string text = "DecoratorB.MethodB1";
Console.WriteLine(text);
return text;
}
}
The key thing to notice in the Decorator class is how the constructor (14) passed IComponent is assigned to a private attribute (13). That is the “composition” we were talking about, and from there, all the magic of the decorator comes.
Decorator (10) now has the ability to completely reuse the functionality of the contained object in (13) and expose its own interface, in which it is free to reuse or modify the behavior of the object (13).
In (15) method MethodI1, we see how DecoratorB provides its own implementation of the interface (10), and in that process, it reuses MethodI1 of the contained object (13).
In addition to the public interface, it is inherited in (10), DecoratorB can add its own properties (12) and methods (16) that add some new functionality to the class.
Typical usage of DecoratorB would look like this.
DecoratorB B = new DecoratorB(new ComponentA()); //(24)
B.StateI = "123";
//B.StateA = "123"; //not possible
B.StateB = "123";
string tmpB1 = B.MethodI1(); //(25)
//string tmpB2 = B.MethodA1(); //not possible //(26)
string tmpB3 = B.MethodB1();
Look at call (25). That is the real reason for the usage of and strength of the Decorator pattern. That is a call to MethodI1 of class DecoratorB, which is using and enhancing the call to MethodI1 of class ComponentA. Since MethodI1 is part of the interface IComponent, even if the resulting object (24) is accessed through reference to IComponent, the call will be available, and it will work. Consumers of reference to IComponent need not even be aware if he is using the original ComponentA or the decorated version. The whole point of why we are doing this Decorator pattern lies in the power of this call. Of course, this is tutorial-level code, in real life, there will be more methods MethodI1, MethodI2, MethodI3, etc. that will all have that power.
We can see that in (26) it is not possible to access the method from ComponentA that is not exposed through interface IComponent. That is a problem because we might have several Components, let’s say ComponentA, ComponentA2, ComponentA3, etc., and each might have its own specific setters to configure itself. The main reason why this is happening is that, again, we do not inherit from ComponentA; we contain an object of class ComponentA, and we access it only through the interface IComponent.
This is one serious deficiency of the Decorator pattern since ComponentA might need some configuring/setup before it is ready for reuse by DecoratorB. It is often bypassed in 2 ways: 1) ComponentA is configured before it is passed to DecoratorB in (24); 2) ComponentA constructor would have parameters to configure itself.
Let us create one more Decorator class.
public class DecoratorC : IComponent //(40)
{
public string StateI { get; set; }
public string StateC { get; set; } //(41)
private IComponent component = null;
public DecoratorC(IComponent comp)
{
component = comp;
}
public string MethodI1(bool print = true)
{
string baseTmp = component.MethodI1(false);
string text = baseTmp + " " + "DecoratorC.MethodI1";
if (print) Console.WriteLine(text);
return text;
}
public string MethodC1() //(42)
{
string text = "DecoratorC.MethodC1";
Console.WriteLine(text);
return text;
}
}
As you can see, DecoratorC is almost the same as DecoratorB. That was done deliberately for the purpose of this article.
Notice that in (41) and (42), DecoratorC is defining some public properties/methods that are specific to itself.
Here is what the usage of DecoratorC looks like.
DecoratorC C = new DecoratorC(new DecoratorB(new ComponentA())); //(27)
C.StateI = "123";
//C.StateA = "123"; //not possible
//C.StateB = "123"; //not possible
C.StateC = "123";
string tmpC1 = C.MethodI1(); //(28)
//string tmpC2 = C.MethodA1(); //not possible //(29)
//string tmpC3 = C.MethodB1(); //not possible //(30)
string tmpC4 = C.MethodC1();
You can see in (27) how multiple decorators can be applied to a component. Let us say immediately, that nothing from a code design point prevents us from applying decorators in a different order, instead of first DecoratorB then DecoratorC, we can apply them in a different order. However, the resulting functionality might differ, so the order is relevant.
Look at call (28). Again, that is the real reason for the usage of and strength of the Decorator pattern. That is a call to MethodI1 of class DecoratorC, which is using and enhancing a call to MethodI1 of class DecoratorB, and that one is using and enhancing a call to MethodI1 of class ComponentA. Again, if we assign (27) to reference to IComponent, the consumer of reference to IComponent does not need to be aware if he is using original components or decorated versions. The whole point of why we are doing this Decorator pattern lies in the power of this call. Again, in real life, there will be more methods, MethodI1, MethodI2, MethodI3, etc., that will all have that power.
You can see in (29) and (30) that access to some public methods of ComponentA and DecoratorB is not possible. As mentioned above, that is a serious deficiency of the Decorator pattern.
Here is the class diagram and code of the whole project Classic Decorator.

public interface IComponent //(1)
{
string StateI { get; set; } //(2)
string MethodI1(bool print = true); //(3)
}
public class ComponentA : IComponent //(4)
{
public string StateI { get; set; } //(5)
public string StateA { get; set; } //(6)
public ComponentA() //(7)
{ }
public string MethodI1(bool print = true) //(8)
{
string text = "ComponentA.MethodI1";
if (print) Console.WriteLine(text);
return text;
}
public string MethodA1() //(9)
{
string text = "ComponentA.MethodA1";
Console.WriteLine(text);
return text;
}
}
public class DecoratorB : IComponent //(10)
{
public string StateI { get; set; } //(11)
public string StateB { get; set; } //(12)
private IComponent component = null; //(13)
public DecoratorB(IComponent comp) //(14)
{
component = comp;
}
public string MethodI1(bool print = true) //(15)
{
string baseTmp = component.MethodI1(false);
string text = baseTmp + " " + "DecoratorB.MethodI1";
if (print) Console.WriteLine(text);
return (text);
}
public string MethodB1() //(16)
{
string text = "DecoratorB.MethodB1";
Console.WriteLine(text);
return text;
}
}
public class DecoratorC : IComponent //(40)
{
public string StateI { get; set; }
public string StateC { get; set; } //(41)
private IComponent component = null;
public DecoratorC(IComponent comp)
{
component = comp;
}
public string MethodI1(bool print = true)
{
string baseTmp = component.MethodI1(false);
string text = baseTmp + " " + "DecoratorC.MethodI1";
if (print) Console.WriteLine(text);
return text;
}
public string MethodC1() //(42)
{
string text = "DecoratorC.MethodC1";
Console.WriteLine(text);
return text;
}
}
class Client
{
static void Main(string[] args)
{
Console.WriteLine("IComponent================================");
IComponent I = new ComponentA(); //(20)
I.StateI = "123";
//I.StateA = "123"; //not possible
string tmpI1 = I.MethodI1(); //(21)
//string tmpI2 = I.MethodA1(); //not possible //(22)
Console.WriteLine("ComponentA================================");
ComponentA A = new ComponentA(); //(23)
A.StateI = "123";
A.StateA = "123";
string tmpA1 = A.MethodI1();
string tmpA2 = A.MethodA1();
Console.WriteLine("DecoratorB================================");
DecoratorB B = new DecoratorB(new ComponentA()); //(24)
B.StateI = "123";
//B.StateA = "123"; //not possible
B.StateB = "123";
string tmpB1 = B.MethodI1(); //(25)
//string tmpB2 = B.MethodA1(); //not possible //(26)
string tmpB3 = B.MethodB1();
Console.WriteLine("DecoratorC================================");
DecoratorC C = new DecoratorC(new DecoratorB(new ComponentA())); //(27)
C.StateI = "123";
//C.StateA = "123"; //not possible
//C.StateB = "123"; //not possible
C.StateC = "123";
string tmpC1 = C.MethodI1(); //(28)
//string tmpC2 = C.MethodA1(); //not possible //(29)
//string tmpC3 = C.MethodB1(); //not possible //(30)
string tmpC4 = C.MethodC1();
Console.WriteLine("Collection================================");
List<IComponent> list = new List<IComponent>();
list.Add(new ComponentA());
list.Add(new DecoratorB(new ComponentA()));
list.Add(new DecoratorC(new DecoratorB(new ComponentA())));
foreach (IComponent iComp in list)
{
iComp.StateI = "123";
string tmpII1 = iComp.MethodI1();
}
Console.ReadLine();
}
}
Here is the result of the sample execution.

Dynamically selecting a type of Component
What the Decorator pattern makes possible, is to dynamically at runtime select which type of component application will use. Let us look at this code.





Join the conversation! Your thoughts help the community grow.