Search code examples
c#.netfactory-pattern

how to implement factory design pattern in c# to draw shapes?


I am trying to learn c# and in c# I am trying to implement a factory design pattern to draw basic shapes like circle, rectangle, triangle, etc. I created a IShape Interface class. And other three Circle, Rectangle, and Triangle class. I also created a ShapeFactory static method. These classes sould be called after from compiler class and draw in another window i.e Output window. Below is the code.

//IShape Class
namespace CPaint.Class
{
    public interface IShape
    {
        void Draw();
    }
}

//Cicle Class
namespace CPaint.Class
{
    internal class Circle : IShape
    {
        //public Output outputWindow;
        private float x;

        private float y;
        private Color color;
        private float radius;
        private Graphics graphics;

        public Circle(Color color, float x, float y, float radius)
        {
            this.color = color;
            this.x = x;
            this.y = y;
            this.radius = radius;
        }

        public void Draw()
        {
            Pen pen = new Pen(Color.Black, 4);
            SolidBrush brush = new SolidBrush(color);
            graphics.FillEllipse(brush, x, y, radius, radius);
            graphics.DrawEllipse(pen, x, y, radius, radius);
        }
    }
}

//Triangle class
namespace CPaint.Class
{
    internal class Triangle : IShape
    {
        private float x;
        private float y;
        private Color color;
        private float side1;
        private float side2;
        private float side3;

        public Triangle(Color color, float x, float y, float side1, float side2, float side3)
        {
            this.color = color;
            this.x = x;
            this.y = y;
            this.side1 = side1;
            this.side2 = side2;
            this.side3 = side3;
        }

        public void Draw()
        {
            //will write drawing code here...
        }
    }
}

//Shape Factory Class
namespace CPaint.Class
{
    public class ShapeFactory
    {
        public static IShape GetShape(string shapeType, Color color, float x, float y, float height, float width, float radius, float side1, float side2, float side3)
        {
            if (shapeType == null)
            {
                return null;
            }

            if (shapeType.Equals("circle"))
            {
                return new Circle(color, x, y, radius);
            }
            else if (shapeType.Equals("rectangle"))
            {
                return new Rectangle(color, x, y, height, width); ;
            }
            else if (shapeType.Equals("triangle"))
            {
                return new Triangle(color, x, y, side1, side2, side3);
            }
            else
            {
                return null;
            }
        }
    }
}

//Compiler Class
if (code[0].Trim().ToLower().Equals("circle"))
{
    try
    {
        int parameter1 = Int32.Parse(code[1]);

        IShape shape = ShapeFactory.GetShape("circle", color, initX, initY, 0, 0, parameter1, 0, 0, 0);
        outputWindow.Show();

        //outputWindow.outputArea.Image=new ShapeFactory.GetShape("circle", color, initX, initY, 0, 0, parameter1, 0, 0, 0);
        //outputWindow.outputArea.Image = shape;

        output = "command executed successfully: parameter is" + parameter1;
        //output = "is numeric ";
    }

    catch (Exception ex)
    {
        Console.WriteLine("Exception Message: " + ex.Message);
        output = "\n Parameter Error : Invalid/Insufficient Parameter. \n";
    }
}

Here in Compiler class, I want to open output window by outputWindow.show(); and then draw the shape in window by outputWindow.OutputArea.Image=...

I got stuck. Please help.


Solution

  • This post explains differences between

    • Factory,
    • Factory Method, and
    • Abstract Factory

    design patterns.

    Since you want to be able to create a whole family of objects that need to be of "the same kind", this can be done with Abstract Factory pattern.

    The factory can have multiple creator methods. You can add parameters to the creator method(s) of the factory.

    IShapesFactory.cs is the interface of the Abstract Factory:

    public interface IShapesFactory
    {
        Circle MakeCircle(Color color, float x, float y, float radius);
        Triangle MakeTriangle(Color color, float x, float y, float side1, float side2, float side3);
    
    }
    

    The implementation of the factory would handle passing the Graphics object to the shapes it creates.

    ShapeFactory.cs

    public class ShapeFactory: IShapeFactory
    {
        private Graphics _graphics;
    
        public ShapeFactory(Graphics graphics)
        {
            _graphics = graphics;
        }
    
        public Circle MakeCircle(Color color, float x, float y, float radius)
        {
            // pass the Graphics object in the constructor of Circle
            return new Circle(_graphics, color, x, y, radius); 
        }
    
        [..other methods of the factory interface]
    }
    

    The factory in use:

    IShapeFactory factory = new ShapeFactory(graphics);
    var circle = factory.MakeCircle(Color.Blue, 10, 10, 20);
    circle.Draw();