Introduction to the Factory Pattern
The Factory Pattern is a creational design pattern that provides an interface for creating objects in a superclass, but allows subclasses to alter the type of objects that will be created. It's a powerful way to encapsulate object creation logic, promoting loose coupling and making your code more flexible and maintainable.
Instead of directly instantiating objects using their constructors, you delegate this responsibility to a factory. This factory class or method is responsible for determining which concrete class to instantiate based on certain conditions or parameters.
Why Use the Factory Pattern?
- Decoupling: It decouples the client code from the concrete classes it needs to instantiate. The client only needs to know about the abstract product and the factory, not the specific implementation details.
- Flexibility: It makes it easy to introduce new product types without modifying the client code. You can simply add a new concrete product and update the factory to create it.
- Maintainability: Centralizing object creation logic in a factory simplifies maintenance and reduces the chances of errors.
- Testability: Decoupling makes it easier to mock dependencies and unit test your code.
Types of Factory Patterns
There are a few variations of the factory pattern:
1. Simple Factory (or Static Factory Method)
A single class that contains a method to create objects. This method often takes a parameter to determine which concrete class to instantiate. While not a "GoF" pattern, it's a common and useful simplification.
using System;
// Product Interface
public interface IProduct
{
void Operation();
}
// Concrete Products
public class ConcreteProductA : IProduct
{
public void Operation()
{
Console.WriteLine("ConcreteProductA.Operation()");
}
}
public class ConcreteProductB : IProduct
{
public void Operation()
{
Console.WriteLine("ConcreteProductB.Operation()");
}
}
// Simple Factory
public static class SimpleProductFactory
{
public static IProduct CreateProduct(string type)
{
switch (type)
{
case "A":
return new ConcreteProductA();
case "B":
return new ConcreteProductB();
default:
throw new ArgumentException("Invalid product type");
}
}
}
// Client Code
public class Client
{
public void DoSomething()
{
IProduct productA = SimpleProductFactory.CreateProduct("A");
productA.Operation();
IProduct productB = SimpleProductFactory.CreateProduct("B");
productB.Operation();
}
}
2. Factory Method
Defines an interface for creating an object, but lets subclasses decide which class to instantiate. The Creator class declares the factory method, which returns an object of the Product type. Concrete Creators implement the factory method to return an instance of a specific Concrete Product.

using System;
// Product Interface
public interface IDocument
{
void Open();
}
// Concrete Products
public class Report : IDocument
{
public void Open()
{
Console.WriteLine("Opening Report Document.");
}
}
public class Resume : IDocument
{
public void Open()
{
Console.WriteLine("Opening Resume Document.");
}
}
// Creator Abstract Class
public abstract class Application
{
// The Factory Method
public abstract IDocument CreateDocument();
public void NewDocument()
{
IDocument doc = CreateDocument();
doc.Open();
}
}
// Concrete Creators
public class ReportApplication : Application
{
public override IDocument CreateDocument()
{
return new Report();
}
}
public class ResumeApplication : Application
{
public override IDocument CreateDocument()
{
return new Resume();
}
}
// Client Code
public class Client
{
public void RunApplication(Application app)
{
app.NewDocument();
}
}
3. Abstract Factory
Provides an interface for creating families of related or dependent objects without specifying their concrete classes. It's useful when you need to create multiple, interconnected objects.

using System;
// Abstract Products
public interface IChair { void SitOn(); }
public interface ITable { void PlaceItemOn(); }
// Concrete Products A
public class ModernChair : IChair { public void SitOn() => Console.WriteLine("Sitting on Modern Chair."); }
public class ModernTable : ITable { public void PlaceItemOn() => Console.WriteLine("Placing item on Modern Table."); }
// Concrete Products B
public class VictorianChair : IChair { public void SitOn() => Console.WriteLine("Sitting on Victorian Chair."); }
public class VictorianTable : ITable { public void PlaceItemOn() => Console.WriteLine("Placing item on Victorian Table."); }
// Abstract Factory
public interface IFurnitureFactory
{
IChair CreateChair();
ITable CreateTable();
}
// Concrete Factories
public class ModernFurnitureFactory : IFurnitureFactory
{
public IChair CreateChair() => new ModernChair();
public ITable CreateTable() => new ModernTable();
}
public class VictorianFurnitureFactory : IFurnitureFactory
{
public IChair CreateChair() => new VictorianChair();
public ITable CreateTable() => new VictorianTable();
}
// Client Code
public class Client
{
public void FurnishRoom(IFurnitureFactory factory)
{
IChair chair = factory.CreateChair();
ITable table = factory.CreateTable();
chair.SitOn();
table.PlaceItemOn();
}
}
When to Use the Factory Pattern
- When a class cannot anticipate the class of objects it must create.
- When a class wants its subclasses to specify the objects it creates.
- When you need to manage object creation logic in a centralized place.
- When you are working with hierarchies of objects and need to create instances of subclasses dynamically.
Benefits and Drawbacks
Benefits
- Improved code flexibility and extensibility.
- Reduced coupling between client code and concrete implementations.
- Centralized object creation, making maintenance easier.
- Supports the Open/Closed Principle.
Drawbacks
- Can introduce more classes and complexity, especially with the Abstract Factory pattern.
- The Simple Factory can become a monolithic "god object" if not managed well.
- Subclasses might need to implement abstract factory methods, adding boilerplate.