Factories

C# Factory Method Design Pattern
Learn how to use the C# Factory Method design pattern to create objects without exposing the creation logic, with quick and easy examples. 100% Source code.
https://www.dofactory.com/net/factory-method-design-pattern

A factory is an object that creates other objects.

Object Graph

flowchart TD
    A[Caller / Coordinator] --> B[Context Factory]
    B --> C["Context (per run)"]
    A --> D["Pipeline Service (DI)"]
    D --> E["Service1 Factory"]
    E --> G["Service1 (per run)"]
    F --> H["Service2 (per run)"]
    G --> I["Result Object"]
    D --> F["Service2 Factory"]
    I --> H
    C --> G
    C --> H
    H --> J["Result + Diagnostics"]

What is it

A factory encapsulates construction logic so callers don’t need to know which concrete types to new or what dependencies to pass. You typically inject factories once, then call them whenever you need a new instance.

public interface IServiceFactory
{
    IService Create(Context context);
}

public sealed class ServiceFactory : IServiceFactory
{
    private readonly IStableDependency _stable;

    public ServiceFactory(IStableDependency stable)
    {
        _stable = stable;
    }

    public IService Create(Context context)
    {
        return new Service(_stable, context);
    }
}

When to use

Best used when you have a workflow that creates short-lived objects per run, and you don’t want the coordinator to manually wire everything together.

It also helps when you expect multiple implementations (e.g., ServiceA vs ServiceB) selected at runtime.

When to use

When not to use

Basic structure

A common setup is: a coordinator injects factories, creates a context per run, then asks factories for the per-run services.

public interface IWorkflow
{
    Result Run(string input);
}

public sealed class Workflow : IWorkflow
{
    private readonly IContextFactory _contextFactory;
    private readonly IServiceFactory _serviceFactory;

    public Workflow(IContextFactory contextFactory, IServiceFactory serviceFactory)
    {
        _contextFactory = contextFactory;
        _serviceFactory = serviceFactory;
    }

    public Result Run(string input)
    {
        var ctx = _contextFactory.Create(input);
        var service = _serviceFactory.Create(ctx);

        return service.Execute();
    }
}

Selecting between multiple implementations

Keep selection logic in one place so it doesn’t leak through the codebase. (Alternatively you can have a keyed service approach)

public enum ServiceKind { A, B }

public interface IServiceFactory
{
    IService Create(ServiceKind kind, Context context);
}

public sealed class ServiceFactory : IServiceFactory
{
    private readonly IStableDependency _stable;

    public ServiceFactory(IStableDependency stable)
    {
        _stable = stable;
    }

    public IService Create(ServiceKind kind, Context context)
    {
        return kind switch
        {
            ServiceKind.A => new ServiceA(_stable, context),
            ServiceKind.B => new ServiceB(_stable, context),
            _ => throw new ArgumentOutOfRangeException(nameof(kind))
        };
    }
}

Trade-offs

Pros

Cons