🎉 Hooray! After 3 years of work, I've finally released the ebook on design patterns! Check it out »

C#: Decorator

Decorator

Decorator is a structural pattern that allows adding new behaviors to objects dynamically by placing them inside special wrapper objects.

Using decorators you can wrap objects countless number of times since both target objects and decorators follow the same interface. The resulting object will get a stacking behavior of all wrappers.

Learn more about Decorator

Application of the pattern in C#

Complexity:

Popularity:

Usage examples: The Decorator is pretty standard in C# code, especially in code related to streams.

Identification: Decorator can be recognized by creational methods or constructor that accept objects of the same class or interface as a current class.

Example: Structure of the Pattern

This example illustrates the structure of the Decorator design pattern. It focuses on answering these questions:

  • What classes does it consists of?
  • What roles do these classes play?
  • In what way the elements of the pattern are related?

Program.cs: Structural Example

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace RefactoringGuru.DesignPatterns.Composite.Structural
{
    class Program
    {
        static void Main(string[] args)
        {
            Client client = new Client();

            var simple = new ConcreteComponent();
            Console.WriteLine("Client: I get a sumple component:");
            client.ClientCode(simple);
            Console.WriteLine();

            ConcreteDecoratorA d1 = new ConcreteDecoratorA(simple);
            ConcreteDecoratorB d2 = new ConcreteDecoratorB(d1);
            Console.WriteLine("Client: Now I get a decorated component:");
            client.ClientCode(d2);
        }
    }

    public class Client
    {
        public void ClientCode(Component component)
        {
            Console.WriteLine("RESULT: " + component.Operation());
        }
    }

    public abstract class Component
    {
        public abstract string Operation();
    }

    class ConcreteComponent : Component
    {
        public override string Operation()
        {
            return "ConcreteComponent";
        }
    }

    abstract class Decorator : Component
    {
        protected Component component;

        public void SetComponent(Component component)
        {
            this.component = component;
        }

        public Decorator(Component component)
        {
            this.component = component;
        }

        public override string Operation()
        {
            if (component != null)
            {
                return component.Operation();
            }
            else
            {
                return string.Empty;
            }
        }
    }

    class ConcreteDecoratorA : Decorator
    {
        public ConcreteDecoratorA(Component comp) : base(comp)
        {
        }

        public override string Operation()
        {
            return "ConcreteDecoratorA(" + base.Operation() + ")";
        }
    }

    class ConcreteDecoratorB : Decorator
    {
        public ConcreteDecoratorB(Component comp) : base(comp)
        {
        }

        public override string Operation()
        {
            return "ConcreteDecoratorB(" + base.Operation() + ")";
        }
    }
}

Output.txt: Output

Client: I get a sumple component:
RESULT: ConcreteComponent

Client: Now I get a decorated component:
RESULT: ConcreteDecoratorB(ConcreteDecoratorA(ConcreteComponent))