Design patterns – Decorator

Decorator pattern (also known as wrapper) is structural pattern. It allows you to attach some funcionality to existing object. It’s more flexible alternative to subclassing as you can attach functionality dynamically in runtime.
Imagine we have class which prints sum of two values.
We can imagine a decorator which adds currency sign or other chars to the printed value.
The class which can be decorated is called concrete component.
Both composite and decorator implement the same interface (or inherit the same base class). Decorator has got a reference to the component.

Our concrete composite with interface:

    /// <summary>
    /// Interface for all components and decorators
    /// </summary>
    interface IValuePrinterComponent
    {
        void Print();
    }
	
    /// <summary>
    /// Component to print sum of two values.
    /// It can be decorated by decorator.
    /// </summary>
    class SumPrinterComponent : IValuePrinterComponent
    {
        protected int _sum;
        public SumPrinterComponent(int a, int b)
        {
            _sum = a + b;
        }

        public virtual void Print()
        {
            Console.WriteLine(_sum);
        }
    }

Our two simple decorators:

    enum Severity
    {
        Minor,
        Major,
        Critical
    }

    /// <summary>
    /// Decorator to decorate printed value with warning sign
    /// </summary>
    class ValuePrinterWarningDecorator : IValuePrinterComponent
    {
        protected IValuePrinterComponent _component;
        private Severity _serverity;

        public ValuePrinterWarningDecorator(IValuePrinterComponent component, Severity severity)
        {
            _component = component;
            _serverity = severity;
        }

        public virtual void Print()
        {
            DecoratePrint();
            _component.Print();
        }

        private void DecoratePrint()
        {
            if (_serverity == Severity.Critical)
                Console.Write("!!!");
            else if (_serverity == Severity.Major)
                Console.Write("!!");
            else
                Console.Write("!");

        }
    }
	
    enum Currency
    {
        Pound,
        Dollar,
    }

    /// <summary>
    /// Decorator to decorate printed value with currency sign
    /// </summary>
    class ValuePrinterCurrencyDecorator : IValuePrinterComponent
    {
        protected IValuePrinterComponent _component;
        private Currency _currency;

        public ValuePrinterCurrencyDecorator(IValuePrinterComponent component, Currency currency)
        {
            _component = component;
            _currency = currency;
        }

        public virtual void Print()
        {
            DecoratePrint();
            _component.Print();
        }

        private void DecoratePrint()
        {
            if (_currency == Currency.Dollar)
                Console.Write("$");
            else if (_currency == Currency.Pound)
                Console.Write("£");

        }
    }

Usage example:

        private static void DecoratorUsage()
        {
            //using printer without any decorator
            var notDecoratedPrinter = new SumPrinterComponent(2, 3);
            notDecoratedPrinter.Print();

            //using printer with currency decorator only
            var currencyDecoratedPrinter = new ValuePrinterCurrencyDecorator(notDecoratedPrinter, Currency.Pound);
            currencyDecoratedPrinter.Print();

            //using printer with warning decorator only
            var warningDecoratedPrinter = new ValuePrinterWarningDecorator(notDecoratedPrinter, Severity.Critical);
            warningDecoratedPrinter.Print();

            //using printer with both decorators
            IValuePrinterComponent fullDecoratedPrinter = new ValuePrinterCurrencyDecorator(notDecoratedPrinter, Currency.Dollar);
            fullDecoratedPrinter = new ValuePrinterWarningDecorator(fullDecoratedPrinter, Severity.Minor);
            fullDecoratedPrinter.Print();
        }
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s