.Net Code Monkey RSS 2.0
 Thursday, April 10, 2008

Background

Recently I have been reading quite a bit about Factory Patterns and Inversion of Control (IOC). However like most principles that are new to me I often find them very hard to visualise at first, and even harder to put them into practise. So I am going to try a simple application using what I believe to be a Factory Pattern. The aim of the game will be to use a factory to produce shapes that will be drawn using .Net's GDI classes in a Windows form application.

This article assumes that the reader is already comfortable with the use of interfaces and inheritance in classes.

The files created in this article can be downloaded from here: 2008-04-11_ShapeMaker.zip (103.25 KB) 

Interfaces

The first thing I'm going to do is to create a Blank Solution, using Visual Studio 2005, which I am going to call ShapeMaker. To this solution I am going to add a New Project which will be a Visual C# Class Library which I am going to call ShapeInterfaces.

I'll close and delete the default Class1.cs class file before I proceed. I shall now add a new Interface called IShape and remove the two unused using statements. To the IShape interface I am going to add a System.Drawing.Point property called Center and import it's namespace after first adding a reference to the System.Drawing assembly. I shall then add a method that is void of a return type and call it Draw().

using System;
using System.Drawing;

namespace Playground.ShapeMaker.ShapeInterfaces
{
    public interface IShape
    {
        /// <summary>
        /// Represents the center of the shape
        /// </summary>
        Point Center { get; set;}

        /// <summary>
        /// The method used to draw the shape
        /// </summary>
        void Draw();
    }
}

All shapes that I intend to create will implement this interface. The Center property will define the center point of the shape, and the Draw() method will allow any user interface to know that when it is required to draw the shape it can call this method and the shape will be responsible for drawing it self.

I'm now going to add two more interfaces which will both implement the IShape interface, the ICircle which will also have a integer Diameter property...

using System;
using System.Drawing;

namespace Playground.ShapeMaker.ShapeInterfaces
{
    public interface ICircle : IShape
    {
        /// <summary>
        /// Represents the diameter of the circle
        /// </summary>
        int Diameter { get; set; }
    }
}

...and the IRectangle which will have a Size property.

using System;
using System.Drawing;

namespace Playground.ShapeMaker.ShapeInterfaces
{
    public interface IRectangle : IShape
    {
        /// <summary>
        /// Represents the size of the rectangle
        /// </summary>
        Size Size { get; set;}
    }
}

Base Classes

I'm now going to add another class library project to the solution which will be my BusinessEntity layer, from which I will also delete the default Class1 class. To the BusinessEntity project I am going to add a folder called BaseClasses. I would probably normally use a separate project for my base classes but for clarity of this example I shall place them in this folder.

To the BaseClassses folder I am going to add a class that all my shape entities will inherit from. I shall call this BaseShape. As I intend for BaseShape to implement the interface IShape I need to add a reference to the ShapeInterfaces project from the BusinessEntity project, and then import the namespace into the BaseShape class.

using System;
using Playground.ShapeMaker.ShapeInterfaces;

namespace Playground.ShapeMaker.BusinessEntity.BaseClasses
{
    public abstract class BaseShape : IShape
    {

    }
}

We have declared the class as abstract as we do not want this class to be able to be constructed. It will just be used a s a base for other classes to derive (inherit) from. Right clicking on the interface name and selecting Implement Interface from the context menu...

... should inject the following code into the class.

#region IShape Members

 public System.Drawing.Point Center
 {
     get
     {
         throw new Exception("The method or operation is not implemented.");
     }
     set
     {
         throw new Exception("The method or operation is not implemented.");
     }
 }

 public void Draw()
 {
     throw new Exception("The method or operation is not implemented.");
 }

 #endregion

We will now need to add a reference to the System.Drawing assembly and import the name space before we can build or we will receive an error. The next task to do is to declare a private field, _center, which will hold our center point data and then we will modify the Center property to access that field. Then we will declare the draw method as abstract so it must be overridden by any derived class.

        private Point _center;

        #region IShape Members

        /// <summary>
        /// Gets or sets the center point of the shape.
        /// </summary>
        public Point Center
        {
            get { return _center; }
            set { _center = value; }
        }

        /// <summary>
        /// All inherited classes will contain this method.
        /// The method will be used to draw it's self.
        /// </summary>
        public abstract void Draw();

        #endregion

Derived classes

Next up is to create two shape classes that will derive from the base class. The first shape we will create will be a Circle. We will add it to the root of the BusinessEntity project, and make it both derive from the BaseShape class and implement the ICircle interface. To make this class derive correctly from the BaseShape class we will need to declare a Draw() method and mark it as an override.

using System;
using Playground.ShapeMaker.BusinessEntity.BaseClasses;
using Playground.ShapeMaker.ShapeInterfaces;

namespace Playground.ShapeMaker.BusinessEntity
{
    public class Circle : BaseShape, ICircle
    {

        #region ICircle Members

        public int Diameter
        {
            get
            {
                throw new Exception("The method or operation is not implemented.");
            }
            set
            {
                throw new Exception("The method or operation is not implemented.");
            }
        }

        #endregion

        /// <summary>
        /// Use this method to draw the shape
        /// </summary>
        public override void Draw()
        {
        }
    }
}

We can now create a private field _diameter and set the Diameter property to access it fully. The next shape we will add will be the Rectangle, which we will do in much the same way, except that we will create a field to hold the size data and access it from the Size property.

using System;
using System.Drawing;
using Playground.ShapeMaker.BusinessEntity.BaseClasses;
using Playground.ShapeMaker.ShapeInterfaces;

namespace Playground.ShapeMaker.BusinessEntity
{
    public class Rectangle : BaseShape, IRectangle
    {
        private Size _size;

        #region IRectangle Members

        /// <summary>
        /// Gets or sets the size of the rectangle.
        /// </summary>
        public Size Size
        {
            get { return _size;  }
            set { _size = value; }
        }

        #endregion

        /// <summary>
        /// Use this method to draw the shape
        /// </summary>
        public override void Draw()
        {
        }
    }
}

Summing up so far...

So far we have two concrete shape classes, Circle and Rectangle that derive from a base shape class. The base shape class implements the IShape interface and the concrete classes implement in turn the IShape interface as well as their respective shape interfaces.

Part 2 will show the next step, which is to build a factory class which will be used to create and return our shape objects at runtime.

Thursday, April 10, 2008 4:03:42 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.Net | C# | Classes | Factory Pattern | Inheritance | Interfaces
All comments require the approval of the site owner before being displayed.
Name
E-mail
(will show your gravatar icon)
Home page

Comment (Some html is allowed: a@href@title, b, blockquote@cite, em, i, strike, strong, sub, sup, u) where the @ means "attribute." For example, you can use <a href="" title=""> or <blockquote cite="Scott">.  

Enter the code shown (prevents robots):

Live Comment Preview
Archive
<October 2014>
SunMonTueWedThuFriSat
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678
Blogroll
 Clemens Vasters
 Harry Pierson
Passion * Technology * Ruthless Competence
 Joshua Flanagan
A .NET Software Developer
 Michael Schwarz's Blog
Developing applications on the Microsoft platform since Windows 3.1!
 Omar Shahine
Yet another Microsoft blogger
 Scot GU
Scott Guthrie lives in Seattle and builds a few products for Microsoft
 Scott Hanselman
Programming Life and the Zen of Computers
 Tom Mertens
Tom's corner
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2014
Duane Wingett
Sign In
Statistics
Total Posts: 53
This Year: 10
This Month: 1
This Week: 0
Comments: 49
Themes
Pick a theme:
All Content © 2014, Duane Wingett
DasBlog theme 'Business' created by Christoph De Baene (delarou)