Simple Factory Pattern in C#

Simple Factory Pattern in C#

Why Use Design Patterns?

Design patterns represent solutions crafted by experienced developesr over years of practice. Here's why they matter:

Build on Proven Solutions - Applying design patterns means leveraging collective industry knowledge rather than starting from scratch. Improved Code Readability - Developers familiar with patterns can quickly understand codebases that follow established conventions. Better Extensibility - Patterns like Strategy enable adding new behaviors through subclasses without modifying existing code, adhering to the Open/Closed Principle. Reduced Coupling - Patterns such as Factory reduce dependencies between classes by having dependent code only reference enterfaces or abstract types. Code Reusability - Adapter pattern, for instance, allows reusing existing functionality by adapting interfaces to meet new requirements. Standardized Problem Solutions - Patterns provide ready-made answers to recurring development challenges. Alternative Reuse Mechanisms - Decorator pattern enables code reuse through composition rather than inheritance.

Among the 23 widely-adopted design patterns, we'll start with the Simple Factory Pattern. Rather than discussing abstract definitions, let's examine a practical scenario to understand its application.

Case Study: Building a Calculator

A typical calculator implementation might look like this:

public class Calculator
{
    public static double Compute(double firstNumber, double secondNumber, string operator)
    {
        double result = 0;

        switch (operator)
        {
            case "+":
                result = firstNumber + secondNumber;
                break;
            case "-":
                result = firstNumber - secondNumber;
                break;
            // Division, multiplication omitted for brevity
        }

        return result;
    }
}

This approach works, and you could reuse this logic across web and mobile pltaforms. However, adding a square root function requires modifying the switch statement, which forces recompilation of all existing operations. The Simple Factory Pattern addresses this limitation by decoupling operation logic.

Implementing the Simple Factory Pattern

Base Operation Class and Concrete Implementations

namespace CalculatorApp
{
    public abstract class Operation
    {
        public double OperandA { get; set; }
        public double OperandB { get; set; }

        public abstract double Calculate();
    }

    public class Addition : Operation
    {
        public override double Calculate()
        {
            return OperandA + OperandB;
        }
    }

    public class Subtraction : Operation
    {
        public override double Calculate()
        {
            return OperandA - OperandB;
        }
    }

    public class Multiplication : Operation
    {
        public override double Calculate()
        {
            return OperandA * OperandB;
        }
    }

    public class Division : Operation
    {
        public override double Calculate()
        {
            if (OperandB == 0)
            {
                throw new InvalidOperationException("Cannot divide by zero.");
            }
            return OperandA / OperandB;
        }
    }
}

Factory Class

namespace CalculatorApp
{
    public static class OperationFactory
    {
        public static Operation CreateOperation(string operatorSymbol)
        {
            Operation operation = null;

            switch (operatorSymbol)
            {
                case "+":
                    operation = new Addition();
                    break;
                case "-":
                    operation = new Subtraction();
                    break;
                case "*":
                    operation = new Multiplication();
                    break;
                case "/":
                    operation = new Division();
                    break;
                default:
                    throw new ArgumentException($"Unsupported operator: {operatorSymbol}");
            }

            return operation;
        }
    }
}

Client Usage

Operation calcOperation = OperationFactory.CreateOperation("+");
calcOperation.OperandA = 15;
calcOperation.OperandB = 27;

double outcome = calcOperation.Calculate();

With this architecture, adding new operations requires creating a new subclass and updating the factory—no changes to existing operation classes or client code needed.

Simple Factory Pattern Structure

The pattern consists of three key participants:

Product - Defines the interface that all concrete products implement Concrete Product - Implements the product interface Factory - Contains logic for creating product instances based on input parameters

Tags: design-patterns simple-factory csharp object-oriented software-architecture

Posted on Sun, 26 Jul 2026 17:18:26 +0000 by TenaciousC