Object Oriented Programming Patterns for Geeks

The Decorator Pattern

 

namespace ooppatterns
{
    using System;
    using System.Collections.Generic;

    internal class Program
    {
        private static void Main( string[] args )
        {
            // Instantiate the client
            IReportRenderer report = new ReportGenerator();

            // Now 'decorate' it
            IReportPart head = new Header( "A Report" );
            head.Append( new Paragraph( "By Moridin8" ) );
            report.Append( head );

            IReportPart title = new Title();
            title.Text = "A Decorator in Action";
            title.Append( new TextLine( " - OOP rules!!" ) );
            report.Append( title );

            IReportPart body = new Paragraph();
            body.Text = @"Lorem ipsum dolor sit amet,"
                        + @"consectetuer adipiscing elit. "
                        + @"Morbi at nunc malesuada erat "
                        + "varius venenatis. Suspendisse eget orci.";

            report.Append( body );

            body = new Paragraph();
            body.Text = @"Vestibulum rhoncus. Nunc ornare metus. "
                        + @"Ut quam. In ante massa, hendrerit at, "
                        + @"facilisis id";

            report.Append( body );

            IReportPart foot = new Footer( "Page 1" );
            report.Append( foot );

            // Make the client object use the decorations...
            report.Render();

            Console.ReadLine();
        }
    }

    // Client object and interfaces
    interface IReportRenderer
    {
        void Append( IReportPart part );
        void Render();
    }

    interface IReportPart : IReportRenderer
    {
        string Text { get; set; }
    }

    class ReportGenerator : IReportRenderer
    {
        private List<IReportPart> _parts = new List<IReportPart>();

        public void Append( IReportPart part )
        {
            this._parts.Add( part );
        }

        public void Render()
        {
            foreach ( IReportPart iRP in this._parts )
                iRP.Render();
        }
    }

    // Decorators for the Client object to be 'decorated' with.
    class Header : IReportPart
    {
        private List<IReportPart> _parts = new List<IReportPart>();
        private string _text;

        public Header( string text )
        {
            this._text = text;
        }

        public string Text
        {
            get { return this._text; }
            set { this._text = value; }
        }

        public void Append( IReportPart part )
        {
            this._parts.Add( part );
        }

        public void Render()
        {
            Console.WriteLine( new string( '=', 20 ) );
            Console.WriteLine( this._text );

            if ( this._parts.Count > 0 )
                foreach ( IReportPart iRP in this._parts )
                    iRP.Render();

            Console.WriteLine( new string( '~', 20 ) );
        }
    }

    class Title : IReportPart
    {
        private List<IReportPart> _parts = new List<IReportPart>();
        private string _text;

        public string Text
        {
            get { return this._text; }
            set { this._text = value; }
        }

        public void Render()
        {
            int addtolen = 0;

            Console.WriteLine();
            Console.Write( this._text );

            if ( this._parts.Count > 0 )
                foreach ( IReportPart iRP in this._parts )
                {
                    addtolen += iRP.Text.Length;
                    iRP.Render();
                }

            Console.WriteLine();

            Console.WriteLine( new string( '-', this._text.Length + addtolen + 1 ) );

            Console.WriteLine();
        }

        public void Append( IReportPart part )
        {
            if ( part is TextLine )
                this._parts.Add( part );
        }
    }

    class Paragraph : IReportPart
    {
        private string _text;

        public Paragraph() { }
        public Paragraph( string text )
        {
            this._text = text;
        }

        public string Text
        {
            get { return this._text; }
            set { this._text = value; }
        }

        public void Render()
        {
            Console.WriteLine( this._text );
            Console.WriteLine();
        }

        public void Append( IReportPart part ) { } // not implemented
    }

    class TextLine : IReportPart
    {
        private string _text;

        public TextLine( string text )
        {
            this._text = text;
        }

        public string Text
        {
            get { return this._text; }
            set { this._text = value; }
        }

        public void Render()
        {
            Console.Write( this._text );
        }

        public void Append( IReportPart part ) { } // not implemented
    }

    class Footer : IReportPart
    {
        private List<IReportPart> _parts = new List<IReportPart>();
        private string _text;

        public Footer( string text )
        {
            this._text = text;
        }

        public string Text
        {
            get { return this._text; }
            set { this._text = value; }
        }

        public void Append( IReportPart part )
        {
            this._parts.Add( part );
        }

        public void Render()
        {
            Console.WriteLine( new string( '~', 20 ) );
            Console.WriteLine( this._text );

            if ( this._parts.Count > 0 )
                foreach ( IReportPart iRP in this._parts )
                    iRP.Render();

            Console.WriteLine( new string( '=', 20 ) );
        }
    }
}