Decorator,Pattern

Erhan 8/7/2016 0

Decorator Pattern

C#
 In this chapter I would like to demonstrate the Decorator Pattern. It provides a new
way of adding responsibilities in the runtime and thus a good alternative to sub
classing.
Challenge
You have an Album class today which is just blank now. Tomorrow the customer
wants a Christmas tree on that. You need to achieve this without modifying the
Album class.
How to achieve this during runtime?
Definition
GoF Definition: "Attach additional responsibilities to an object dynamically.
Decorators provide a flexible alternative to sub classing for extending functionality"
Closed for Modification and Open for Extension
One of the main challenges we face in development is Change. The Closed for
Modification and Open for Extension principle says a new functionality can be added
by keeping the original code unchanged.
Example:
We will modify the original Album class to incorporate the Christmas tree on it. This
should not be the best approach. There is a better approach to this. We can still keep
the Album class unchanged and add the Christmas tree to it. Everything happens in
the runtime… that is the cool part of it.
Some more examples
We can see real life controls like Form, Button etc. There would be a Form class with
built-in functionality. Still the user can use it and add new controls to it / extend the
functionality. Here we will be basically deriving from the existing Form/Button class
and add new methods or properties to it.
The difference between the above approach and Decorator pattern is that, in the
Decorator pattern, it is done during runtime.
Conclusion on Change
So basically we can conclude that whenever changes are required, the possible
solutions could be:
?h Change the original class
?h Subclass it and create instance of subclass
?h Use Decorator Pattern and still using the original class instance
Here we are going to see how we can use Decorator Pattern to help with the
following scenario.
Requirement
The requirement here would be to provide a default Album object and based on
dynamic requirement from the user in runtime, we have to draw other pictures to
the album.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;

namespace DecoratorPattern.Classes
{
    public class Album
    {
        public Graphics Graphics
        {
            get;
            set;
        }

        public Album()
        {
        }

        public Album(Graphics graphics)
        {
            Graphics = graphics;
        }

        public virtual void Draw()
        {
            Graphics.Clear( Color.White);
        }
    }
}
**************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DecoratorPattern.Classes
{
public abstract class AlbumDecorator : Album
{
    protected Album _album;

    public AlbumDecorator(Album album)
    {
        _album = album;
    }

    public override void Draw()
    {
        _album.Draw();
    }
}
}

****************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace DecoratorPattern.Classes
{
    public class ChristmasTreeDecorator : AlbumDecorator
    {
        public ChristmasTreeDecorator(Album album)
            : base(album)
        {
            Graphics = album.Graphics;
        }

        public override void Draw()
        {
            _album.Draw();
            this.InternalDraw();
        }

        private void InternalDraw()
        {
            _album.Graphics.DrawImage( Images.ChristmasTree, new Point(30, 60));
        }
    }
}
*****************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace DecoratorPattern.Classes
{
    public class SantaClausDecorator : AlbumDecorator
    {
        public SantaClausDecorator(Album album)
            : base(album)
        {
            Graphics = album.Graphics;
        }

        public override void Draw()
        {
            _album.Draw();
            this.InternalDraw();
        }

        private void InternalDraw()
        {
            _album.Graphics.DrawImage( Images.SantaClaus, new Point(230, 20));
        }
    }
}
***********************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace DecoratorPattern.Classes
{
    public class StarDecorator : AlbumDecorator
    {
        public StarDecorator(Album album)
            : base(album)
        {
            Graphics = album.Graphics;
        }

        public override void Draw()
        {
            _album.Draw();
            this.InternalDraw();
        }

        private void InternalDraw()
        {
            _album.Graphics.DrawImage( Images.Star, new Point(7, 4));
            _album.Graphics.DrawImage( Images.Star, new Point(156, 55));
            _album.Graphics.DrawImage( Images.Star, new Point(164, 192));
            _album.Graphics.DrawImage( Images.Star, new Point(190, 345));
            _album.Graphics.DrawImage( Images.Star, new Point(369, 362));
            _album.Graphics.DrawImage( Images.Star, new Point(504, 360));
        }
    }
}
*************************************************
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DecoratorPattern.Classes;

namespace DecoratorPattern
{
    public partial class MainForm : Form
    {
        private Graphics _graphics;
        private Album _album;

        public MainForm()
        {
            InitializeComponent();

            // Create Instances
            _graphics = pbxMain.CreateGraphics();
            _album = new Album (_graphics);
            _album.Draw();
        }

        private void btnAddChtristmasTree_Click(object sender, EventArgs e)
        {
            _album = new ChristmasTreeDecorator (_album);
            _album.Draw();
        }

        private void btnAddSantaClaus_Click(object sender, EventArgs e)
        {
            _album = new SantaClausDecorator (_album);
            _album.Draw();
        }

        private void pbxMain_MouseDown(object sender, MouseEventArgs e)
        {
            MessageBox.Show(e.X.ToString()   " "   e.Y.ToString());
        }

        private void btnAddStars_Click(object sender, EventArgs e)
        {
            _album = new StarDecorator (_album);
            _album.Draw();
        }
    }
}
  
 

Report Bug

Please Login to Report Bug

Reported Bugs

Comments

Please Login to Comment

Comments