Core Spark (C# Challenge)

C# Challenge

An advanced C# assistant to help with challenging C# coding questions/requests.

Demonstrate the Factory Method Pattern Create a Shape Factory that produces different types of shapes (e.g., Circle, Square, Triangle). Implement a factory method to instantiate shape objects based on a specified type, allowing easy extension to support new shapes in the future. Create a console application to demonstrate you shape factory.


Responses From Spark Variants that Implement the Core Spark (C# Challenge)

Sure, I'll create a C# .NET 8 solution that demonstrates the Factory Method Pattern by implementing a Shape Factory. This solution will include the following:

  1. Shape interface and concrete shape classes (Circle, Square, Triangle).
  2. ShapeFactory class with a factory method to instantiate shape objects.
  3. A console application to demonstrate the Shape Factory.
  4. MS Test unit tests to validate the functionality.

Here's the complete solution:

Step 1: Define the Shape Interface and Concrete Shape Classes

// IShape.cs
namespace ShapeFactoryDemo.Shapes
{
    /// <summary>
    /// Interface for different types of shapes.
    /// </summary>
    public interface IShape
    {
        /// <summary>
        /// Draws the shape.
        /// </summary>
        void Draw();
    }
}

// Circle.cs
namespace ShapeFactoryDemo.Shapes
{
    /// <summary>
    /// Represents a Circle shape.
    /// </summary>
    public class Circle : IShape
    {
        /// <summary>
        /// Draws the Circle shape.
        /// </summary>
        public void Draw()
        {
            Console.WriteLine("Drawing a Circle.");
        }
    }
}

// Square.cs
namespace ShapeFactoryDemo.Shapes
{
    /// <summary>
    /// Represents a Square shape.
    /// </summary>
    public class Square : IShape
    {
        /// <summary>
        /// Draws the Square shape.
        /// </summary>
        public void Draw()
        {
            Console.WriteLine("Drawing a Square.");
        }
    }
}

// Triangle.cs
namespace ShapeFactoryDemo.Shapes
{
    /// <summary>
    /// Represents a Triangle shape.
    /// </summary>
    public class Triangle : IShape
    {
        /// <summary>
        /// Draws the Triangle shape.
        /// </summary>
        public void Draw()
        {
            Console.WriteLine("Drawing a Triangle.");
        }
    }
}

Step 2: Implement the ShapeFactory Class

// ShapeFactory.cs
namespace ShapeFactoryDemo.Factory
{
    using ShapeFactoryDemo.Shapes;

    /// <summary>
    /// Factory class to create shape objects.
    /// </summary>
    public class ShapeFactory
    {
        /// <summary>
        /// Factory method to create shape objects based on the specified type.
        /// </summary>
        /// <param name="shapeType">The type of shape to create.</param>
        /// <returns>An instance of IShape.</returns>
        public IShape CreateShape(string shapeType)
        {
            return shapeType.ToLower() switch
            {
                "circle" => new Circle(),
                "square" => new Square(),
                "triangle" => new Triangle(),
                _ => throw new ArgumentException("Invalid shape type", nameof(shapeType)),
            };
        }
    }
}

Step 3: Create a Console Application to Demonstrate the Shape Factory

// Program.cs
namespace ShapeFactoryDemo
{
    using ShapeFactoryDemo.Factory;
    using ShapeFactoryDemo.Shapes;

    class Program
    {
        static void Main(string[] args)
        {
            ShapeFactory shapeFactory = new ShapeFactory();

            IShape circle = shapeFactory.CreateShape("circle");
            circle.Draw();

            IShape square = shapeFactory.CreateShape("square");
            square.Draw();

            IShape triangle = shapeFactory.CreateShape("triangle");
            triangle.Draw();

            // Uncomment the following line to see the exception handling
            // IShape unknown = shapeFactory.CreateShape("pentagon");
            // unknown.Draw();
        }
    }
}

Step 4: Implement MS Test Unit Tests

// ShapeFactoryTests.cs
using Microsoft.VisualStudio.TestTools.UnitTesting;
using ShapeFactoryDemo.Factory;
using ShapeFactoryDemo.Shapes;

namespace ShapeFactoryDemo.Tests
{
    [TestClass]
    public class ShapeFactoryTests
    {
        private ShapeFactory _shapeFactory;

        [TestInitialize]
        public void Setup()
        {
            _shapeFactory = new ShapeFactory();
        }

        [TestMethod]
        public void CreateShape_ShouldReturnCircle_WhenShapeTypeIsCircle()
        {
            IShape shape = _shapeFactory.CreateShape("circle");
            Assert.IsInstanceOfType(shape, typeof(Circle));
        }

        [TestMethod]
        public void CreateShape_ShouldReturnSquare_WhenShapeTypeIsSquare()
        {
            IShape shape = _shapeFactory.CreateShape("square");
            Assert.IsInstanceOfType(shape, typeof(Square));
        }

        [TestMethod]
        public void CreateShape_ShouldReturnTriangle_WhenShapeTypeIsTriangle()
        {
            IShape shape = _shapeFactory.CreateShape("triangle");
            Assert.IsInstanceOfType(shape, typeof(Triangle));
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void CreateShape_ShouldThrowArgumentException_WhenShapeTypeIsInvalid()
        {
            _shapeFactory.CreateShape("pentagon");
        }
    }
}

Guidelines and Suggestions for Improvements and Use

  1. Extensibility: The factory method pattern allows easy extension to support new shapes. Simply create a new shape class implementing IShape and update the factory method in ShapeFactory.

  2. Error Handling: The factory method throws an ArgumentException for invalid shape types. This can be enhanced by using custom exceptions for better clarity.

  3. Performance: The current implementation is straightforward and performs well for the given use case. For more complex scenarios, consider using dependency injection and more advanced design patterns.

  4. Documentation: Ensure XML documentation comments are maintained and updated as the code evolves.

  5. Testing: The provided unit tests cover basic scenarios and edge cases. Continue to add tests as new shapes and functionalities are introduced.

This solution demonstrates the Factory Method Pattern effectively and provides a solid foundation for further enhancements and extensions.