creational

Factory Method

Define an interface for creating an object, but let subclasses decide which class to instantiate.

Your code needs to create an object, but you do not want it tied to one specific class.

The moment you write new PdfReport(), that line only works for PDFs. Supporting Excel means going back and adding an if. Do this in ten places and every new format means ten edits to code that was already tested and working.

Factory Method moves the choice into one overridable method. The main logic calls that method and works with whatever comes back. To add a format, you write a new subclass instead of editing the old flow.

A logistics company has a createTransport() method. Road logistics returns a Truck; Sea logistics returns a Ship.

Key Concepts

1
A base class declares a method whose job is to create the object, such as createReport(). It may be abstract, or it may return a sensible default.
createReport()
2
The rest of the base class calls that method whenever it needs the object. Importantly, it only uses the interface. It never knows which concrete class it received.
3
Each subclass overrides the method and returns a different type. PdfReportCreator returns a PdfReport, ExcelReportCreator returns an ExcelReport. The shared logic above them does not change.
PdfReportCreatorPdfReportExcelReportCreatorExcelReport

When to use it

  • You don't know ahead of time which class to instantiate
  • Subclasses should control what gets created
  • Building a framework where users plug in implementations

Watch out for

  • Adds a parallel class hierarchy — every new product usually means a new creator subclass, which is a lot of ceremony when you only have two variants
  • Often confused with Abstract Factory in interviews: Factory Method creates ONE product via inheritance, Abstract Factory creates FAMILIES of related products via composition
  • A simple static factory method or a Map<String, Supplier<T>> is frequently the better answer — reach for the full pattern only when subclasses genuinely need to vary the product
java
public abstract class LogisticsApp {
    public abstract Transport createTransport();
    public void planDelivery() {
        Transport t = createTransport();
        t.deliver();
    }
}
public class RoadLogistics extends LogisticsApp {
    public Transport createTransport() { return new Truck(); }
}
public class SeaLogistics extends LogisticsApp {
    public Transport createTransport() { return new Ship(); }
}