04 Dec 2023



Advanced

The Decorator design pattern is a structural pattern that allows behavior to be added to an individual object, either statically or dynamically, without affecting the behavior of other objects from the same class. In C#, the Decorator pattern typically involves the following main components:

  1. Component Interface:

    • Declares the interface for objects that can have responsibilities added or removed dynamically.
    public interface IComponent
    {
        void Operation();
    }
    
  2. Concrete Component:

    • Implements the Component interface.
    • Defines the basic behavior to which additional responsibilities can be attached.
    public class ConcreteComponent : IComponent
    {
        public void Operation()
        {
            Console.WriteLine("Concrete Component Operation");
        }
    }
    
  3. Decorator:

    • Implements the Component interface.
    • Maintains a reference to a Component object and defines an interface that conforms to the Component's interface.
    • Redirects requests to the Component and may perform additional actions before or after forwarding the request.
    public abstract class Decorator : IComponent
    {
        protected IComponent component;
    
        public Decorator(IComponent component)
        {
            this.component = component;
        }
    
        public virtual void Operation()
        {
            if (component != null)
            {
                component.Operation();
            }
        }
    }
    
  4. Concrete Decorator:

    • Extends the Decorator class.
    • Adds responsibilities to the component.
    • Overrides methods of the Decorator to provide specific behavior.
    public class ConcreteDecoratorA : Decorator
    {
        public ConcreteDecoratorA(IComponent component) : base(component)
        {
        }
    
        public override void Operation()
        {
            base.Operation();
            AddedBehavior();
        }
    
        private void AddedBehavior()
        {
            Console.WriteLine("Concrete Decorator A Added Behavior");
        }
    }
    
    public class ConcreteDecoratorB : Decorator
    {
        public ConcreteDecoratorB(IComponent component) : base(component)
        {
        }
    
        public override void Operation()
        {
            base.Operation();
            AddedBehavior();
        }
    
        private void AddedBehavior()
        {
            Console.WriteLine("Concrete Decorator B Added Behavior");
        }
    }
    
  5. Client:

    • Uses objects conforming to the Component interface.
    • Can attach decorators to components dynamically.
    class Client
    {
        static void Main()
        {
            IComponent component = new ConcreteComponent();
            component.Operation();
    
            Console.WriteLine("\nAdding ConcreteDecoratorA:");
            IComponent decoratedA = new ConcreteDecoratorA(component);
            decoratedA.Operation();
    
            Console.WriteLine("\nAdding ConcreteDecoratorB:");
            IComponent decoratedB = new ConcreteDecoratorB(component);
            decoratedB.Operation();
        }
    }
    

In this example:

  • IComponent is the interface that defines the basic operation.
  • ConcreteComponent is the concrete implementation of IComponent.
  • Decorator is an abstract class implementing the IComponent interface, containing a reference to another IComponent object. It serves as the base class for concrete decorators.
  • ConcreteDecoratorA and ConcreteDecoratorB are concrete decorator classes that add specific behavior before or after calling the operation of the wrapped IComponent.
  • The Client demonstrates how to create and use decorated components.

The Decorator pattern allows for the dynamic attachment of additional responsibilities to an object in a flexible and reusable way, without altering its code.

software-design-patterns
decorator-design-pattern