Skip to main content

Factory Method Pattern

Definition​

The Factory Method defines an interface for creating objects, but lets subclasses decide which class to instantiate. The method defers instantiation to derived classes, decoupling client code from concrete types.

Coffee Shop Example​

A coffee shop takes orders from different channels β€” walk-in customers, a mobile app, and a drive-through. Each channel creates coffee differently (different defaults, sizes, extras), but the ordering process is the same.

Structure​

Implementation​

// The Creator abstract class
public abstract class CoffeeOrderBase
{
// Factory Method β€” subclasses decide what to create
public abstract Coffee CreateCoffee();

// Template method β€” shared logic that uses the factory method
public string PlaceOrder()
{
var coffee = CreateCoffee();
return $"Order placed: {coffee}";
}
}

// Concrete Creators β€” each creates a different coffee
public class WalkInOrder : CoffeeOrderBase
{
public override Coffee CreateCoffee() => new Espresso();
}

public class MobileAppOrder : CoffeeOrderBase
{
public override Coffee CreateCoffee() => new Latte { Size = CupSize.Large };
}

public class DriveThroughOrder : CoffeeOrderBase
{
public override Coffee CreateCoffee() => new Cappuccino();
}

// Usage
CoffeeOrderBase order = new MobileAppOrder();
Console.WriteLine(order.PlaceOrder());
// Output: Order placed: Latte (Large) β€” $4.00 [Espresso Shot, Steamed Milk]

With Parameters β€” Choosing Coffee Type at Runtime​

public enum CoffeeType { Espresso, Latte, Cappuccino }

public class SmartCoffeeOrder : CoffeeOrderBase
{
private readonly CoffeeType _type;
private readonly CupSize _size;

public SmartCoffeeOrder(CoffeeType type, CupSize size = CupSize.Medium)
{
_type = type;
_size = size;
}

public override Coffee CreateCoffee() => _type switch
{
CoffeeType.Espresso => new Espresso { Size = _size },
CoffeeType.Latte => new Latte { Size = _size },
CoffeeType.Cappuccino => new Cappuccino { Size = _size },
_ => throw new ArgumentException($"Unknown coffee type: {_type}")
};
}

// Usage
var order = new SmartCoffeeOrder(CoffeeType.Latte, CupSize.Large);
Console.WriteLine(order.PlaceOrder());
// Output: Order placed: Latte (Large) β€” $4.00 [Espresso Shot, Steamed Milk]

Simple Factory (Not a GoF Pattern, But Common)​

A Simple Factory is a single class with one method that creates objects based on a parameter. It's not a true GoF pattern but is widely used when you don't need subclass-based flexibility.

public static class CoffeeFactory
{
public static Coffee Create(CoffeeType type, CupSize size = CupSize.Medium) => type switch
{
CoffeeType.Espresso => new Espresso { Size = size },
CoffeeType.Latte => new Latte { Size = size },
CoffeeType.Cappuccino => new Cappuccino { Size = size },
_ => throw new ArgumentException($"Unknown coffee type: {type}")
};
}

// Usage
var coffee = CoffeeFactory.Create(CoffeeType.Espresso, CupSize.Small);
Simple Factory vs Factory Method

Simple Factory β€” one class, one method, parameter-based. Easier, good enough for most cases. Factory Method β€” inheritance-based, subclasses override creation. Better when creation logic differs per context.

.NET Real-World Usage​

  • IHttpMessageHandlerFactory.CreateHandler() β€” creates HTTP handlers
  • DbProviderFactory.CreateConnection() β€” creates DB connections for different providers
  • TaskFactory.StartNew() β€” creates and schedules tasks
  • Activator.CreateInstance() β€” runtime type instantiation

When to Use​

  • A class can't anticipate which object it must create
  • You want to delegate instantiation to subclasses
  • You need to decouple client code from concrete product classes
  • You're building a framework where users plug in their own implementations

When NOT to Use​

  • When there's only one product type β€” a simple constructor is enough
  • When the creation logic is trivial β€” don't add a factory just for new Foo()
  • When you need families of related products β€” use Abstract Factory instead

Key Takeaways​

  • The Factory Method is about deferring creation to subclasses β€” the base class doesn't know which concrete product it gets
  • The client (base class) works with the abstract product interface β€” it's decoupled from concrete types
  • Open/Closed Principle: add new product types by adding new creator subclasses, without modifying existing code
  • A Simple Factory is often good enough β€” use the GoF pattern when subclass-based flexibility is needed

Interview Questions​

Q: What's the difference between Simple Factory and Factory Method? Simple Factory is one class with a switch/if β€” it's centralized. Factory Method uses inheritance β€” each subclass overrides the creation method.

Q: How does Factory Method relate to Open/Closed Principle? New product types are added by creating new creator subclasses. Existing code never changes β€” it only calls the abstract factory method.

Q: When would you use Factory Method over Abstract Factory? Factory Method creates one product type. Abstract Factory creates families of related products. Use Factory Method when you only need one product.