Factory Method vs Abstract Factory — when to use each
Factory Method — defines a method whose implementation determines which concrete type to instantiate.
public abstract class DocumentCreator {
public abstract IDocument Create(); // factory method
public IDocument NewDocument() {
var doc = Create();
doc.AddHeader();
return doc;
}
}
public class PdfDocumentCreator : DocumentCreator {
public override IDocument Create() => new PdfDocument();
}
The base class describes the algorithm using the product. Subclasses decide which product. One product per factory.
Abstract Factory — provides an interface for creating families of related products without specifying their concrete classes.
public interface IUIFactory {
IButton CreateButton();
ICheckbox CreateCheckbox();
IDropdown CreateDropdown();
}
public class MaterialUiFactory : IUIFactory {
public IButton CreateButton() => new MaterialButton();
public ICheckbox CreateCheckbox() => new MaterialCheckbox();
public IDropdown CreateDropdown() => new MaterialDropdown();
}
public class FluentUiFactory : IUIFactory { /* Fluent variants */ }
Multiple products that should be created together — switching factories switches the whole family consistently.
When to use which:
- One product family with a creation step you want to vary → Factory Method
- Multiple related products that must match (themes, OS-specific widgets, DB-specific commands) → Abstract Factory
Modern C# reality: dependency injection containers + interfaces already give you Abstract Factory's flexibility with less code. Register concrete services per environment; consumers take the interfaces. Reach for the named patterns only when your team's vocabulary needs the precision.