Last Updated: February 22, 2026

The Decorator Design Pattern is a structural pattern that lets you dynamically add new behavior or responsibilities to objects without modifying their underlying code.
It’s particularly useful in situations where:
if-else logic for optional features.Let’s walk through a real-world example to see how we can apply the Decorator Pattern to build a modular, flexible, and easily composable system for enhancing object functionality.
Imagine you are building a rich text rendering system, something like a simplified word processor or a markdown preview tool. At the core of your system is a TextView component that renders plain text on screen.
The first version works great. Then the requirements start growing:
Your first instinct might be to create a subclass for each variation:
The red nodes are combination subclasses that only exist because inheritance cannot mix and match behaviors.
With just 3 features (bold, italic, underline), you already need 7 subclasses to cover every possible combination. Add a 4th feature like highlight, and that jumps to 15. A 5th feature (strikethrough) brings it to 31. The formula is 2^n - 1, where n is the number of features.
Here is what the naive code looks like:
While this code works for a small number of features, it collapses under its own weight as the system grows:
For every new combination of features, you need a new subclass. The number of subclasses grows exponentially: n features produce 2^n - 1 combinations. With 5 formatting options (bold, italic, underline, highlight, strikethrough), that is 31 subclasses, most of which are just recombinations of the same logic.
You cannot change features at runtime. Want to let the user toggle bold on and off based on a preference? You need to swap the entire object with a different subclass. There is no way to add or remove a single behavior dynamically.
Every time a new feature like highlight or shadow is introduced, you need to create new subclasses for every existing combination that includes the new feature. Existing classes stay untouched, but the number of new classes you must add grows with every feature.
The bold logic is duplicated across BoldTextView, BoldItalicTextView, BoldUnderlineTextView, and every other class that includes bold. If you change how bold rendering works, you must update every class that includes it.
We need a way to:
This is exactly where the Decorator pattern fits in.
The Decorator pattern is a structural pattern that attaches additional responsibilities to an object dynamically. Instead of extending a class through inheritance, it wraps the original object inside another object that adds the new behavior.
Two characteristics define the pattern:
This creates a layered effect, where decorators can be stacked to apply multiple enhancements without creating a complex inheritance tree.
Think of a plain coffee. Now add milk. Now add sugar. Each addition enhances the original but doesn’t change the base.
The Decorator Pattern works the same way: stacking behaviors while keeping the core intact.
Decorator has four participants.
TextView)Declares the common interface that both the core object and all decorators implement.
In our text rendering example, TextView is the Component. It declares a single render() method that every participant implements.
PlainTextView)The base object that can be wrapped with decorators. It provides the default behavior.
In our example, PlainTextView renders raw text with no formatting. It is the starting point that decorators build upon.
TextDecorator)An abstract class that implements the Component interface and holds a reference to another Component. It forwards calls to the wrapped object.
In our example, TextDecorator is the abstract base for all formatting decorators. It accepts any TextView in its constructor and delegates render() to it.
BoldDecorator, ItalicDecorator, etc.)Extend the base decorator to add new functionality before/after calling the wrapped component’s method.
In our example, BoldDecorator wraps the output in <b> tags, ItalicDecorator in <i> tags, and UnderlineDecorator in <u> tags.
Here is the Decorator workflow, step by step:
The client creates a PlainTextView with the text "Hello". This is the core object.
The client wraps the plain text view inside a BoldDecorator. The decorator stores a reference to the plain text view.
The client wraps the bold decorator inside an ItalicDecorator, then wraps that inside an UnderlineDecorator. Each decorator stores a reference to the previous one.
The client calls render() on the outermost decorator (UnderlineDecorator).
UnderlineDecorator prints <u>, then calls render() on its inner object (ItalicDecorator). ItalicDecorator prints <i>, then calls render() on its inner object (BoldDecorator). BoldDecorator prints <b>, then calls render() on its inner object (PlainTextView).
PlainTextView prints "Hello". BoldDecorator prints </b>. ItalicDecorator prints </i>. UnderlineDecorator prints </u>. The final output is <u><i><b>Hello</b></i></u>.
Let’s implement the Decorator Pattern to enable flexible styling of text elements such as bold, italic, underline, and combinations of these.
Instead of creating a subclass for every combination, we create one class per feature and wrap them around each other. Each decorator adds its behavior and delegates the rest to the next object in the chain.
This is the shared contract. Both the base component and all decorators implement it. The render() method outputs the formatted text.
This is the base object that renders plain text. It implements TextView and holds the raw text content. No formatting, no decoration, just the core data.
This class implements TextView and holds a reference to another TextView. It is the bridge between the interface and the concrete decorators. Every decorator extends this class, inheriting the reference and the delegation pattern.
Each decorator adds one specific formatting layer. It prints its tag, delegates to the wrapped component, then closes its tag.
The client creates the base component and wraps it with any combination of decorators at runtime. No subclass explosion. No hardcoded combinations.
To show the Decorator pattern in a completely different domain, let's build a coffee ordering system. The interface tracks both the cost and the description of a coffee order. Decorators add condiments, each with its own price.
Notice how MilkDecorator is applied twice in Order 3. This is perfectly valid. Each decorator is independent, and stacking the same one multiple times adds its cost again. With inheritance, you would need a separate DoubleMilkSugarWhippedCreamCoffee class. With Decorator, you just wrap it twice.