Decorator Pattern: Gift Wrapping
The Decorator Pattern allows you to add new features to existing objects without changing their structure. You wrap the original object in another object that adds extra behaviour, so you can add features as needed.
This is often used to add things like logging, security, or UI decorations (such as borders or scrollbars) to many parts of an application. Decorators can be stacked, so you can add many new features step by step.
Real-Life Analogy: Gift Wrapping
Imagine you are wrapping a birthday gift. You start with the gift box, then wrap it in paper, tie a ribbon, and finally add a card.
Each wrapping layer adds something new — it protects the gift, makes it look nicer, or gives it meaning. But the gift itself doesn’t change. You can add as many layers as you like, in any order. That’s how the Decorator Pattern works: each wrapper adds new behaviour to the object.

Benefits of Decorator Pattern
This pattern keeps your base code clean. You don't need to create many subclasses to add features. Instead, you build new behaviour by stacking decorators.
- Supports the open/closed principle — add features without changing code
- Lets you mix and match features at runtime
- Avoids large inheritance trees
What to Implement
To use the Decorator Pattern in C#, you need:
- Component Interface: Defines the basic operations
- Concrete Component: The object that does the real work
- Base Decorator: A class that implements the interface and stores a reference to the component
- Concrete Decorators: These extend the base decorator and add new behaviour
How It Works in C#
// Component Interface
public interface IGift
{
string GetDescription();
}
// Concrete Component
public class GiftBox : IGift
{
public string GetDescription() => "Gift box";
}
// Base Decorator
public abstract class GiftDecorator : IGift
{
protected IGift gift;
public GiftDecorator(IGift gift)
{
this.gift = gift;
}
public virtual string GetDescription() => gift.GetDescription();
}
// Concrete Decorators
public class Ribbon : GiftDecorator
{
public Ribbon(IGift gift) : base(gift) { }
public override string GetDescription() => gift.GetDescription() + " + ribbon";
}
public class Card : GiftDecorator
{
public Card(IGift gift) : base(gift) { }
public override string GetDescription() => gift.GetDescription() + " + greeting card";
}
Client code:
IGift gift = new GiftBox();
gift = new Ribbon(gift);
gift = new Card(gift);
Console.WriteLine(gift.GetDescription()); // Gift box + ribbon + greeting card
When Should You Use It?
Use the Decorator Pattern when you want to add features to one object — not every object of that class. It's useful when inheritance would make the system too complicated.
Use it when:
- You want to add features to an object without modifying its class
- You want to combine behaviours in flexible ways
- Subclassing would lead to too many combinations
When Not to Use It: Don't use it when you only have a few fixed options and simple inheritance would be easier.
Where Is It Used in the Real World?
The Decorator Pattern is popular in frameworks that allow feature extension at runtime. It is widely used for adding cross-cutting concerns to classes.
- UI frameworks (wrapping controls with features like scrolling, borders, etc.)
- Stream handling (I/O decorators in Java, .NET)
- Logging and monitoring (adding behaviours to services)
- Middleware (chaining HTTP request handlers)
Final Thoughts
The Decorator Pattern is like wrapping a present — start with the gift, then add paper, ribbon, and a tag.
Each layer adds something special. You never touch the gift directly — and you can unwrap or swap layers as needed. That's the power of decorators.