Factory Method in C++

Creational Easy

In one sentence: Factory Method puts object creation behind a virtual function, so a subclass — not the code using the object — decides which concrete class gets built.

Real-world analogy

A pizzeria chain writes its serving procedure once, at head office: make the base, add the toppings, bake it, box it, hand it over. Every franchise in the world follows those five steps in that order. But the procedure never says what the base is. Step one is a blank: "make the base — house style."

Each franchise fills in that blank its own way. Naples stretches a thin crust. Chicago presses a deep dish. Neither branch rewrites the other four steps, and head office never learns what dough anyone uses — it only needs the base to be round, flat, and bakeable, which is all the rest of the procedure depends on.

The customer at the counter orders "a pizza." Not "a Chicago deep dish." They get handed a box, and everything after that — carrying it, opening it, eating it — works identically whichever branch they walked into.

Mapping the analogy to the pattern:

  • The head-office serving procedure → the Creator's operation that uses the product without knowing its class — Report::print() in the example below.
  • The blank step "make the base" → the virtual factory method: declared by the Creator, never implemented by it.
  • Each franchise → a ConcreteCreator, which overrides that one step and changes nothing else.
  • Thin crust and deep dish → the ConcreteProducts, each built by exactly one franchise.
  • "Round, flat, bakeable" — all the procedure relies on → the abstract Product interface; the customer ordering "a pizza" is the client code, which names no branch and no dough.

Another angle: a courier network's dispatch sheet. Every depot runs the same three steps — load the vehicle, drive the route, collect the signature — and each depot decides whether "the vehicle" is a van, a bike, or a handcart. The dispatcher writes one sheet and never picks a vehicle.

The problem

You wrote a report generator that produces HTML. It works, so people ask for Markdown too. Now your code is full of this:

if (format == "html")     doc = new HtmlDocument();
else if (format == "md")  doc = new MarkdownDocument();

Two things go wrong:

  1. Every new format touches old code. Adding PDF means editing the same if chain in every place that creates a document — and you will miss one.
  2. The workflow is welded to the type. The logic "print a heading, then a paragraph" is identical for all formats, but it sits in a function that names concrete classes, so you can't reuse it.

The solution

Split the class in two roles:

  1. The creator holds the workflow and declares a virtual method that returns the product — that's the factory method. It never says new HtmlDocument.
  2. Concrete creators are subclasses that override the factory method and return one specific product.

The workflow code now talks only to the product's abstract interface. Adding a format means writing two small new classes and changing nothing that already works. GoF's second name for the pattern captures it in two words: a Virtual Constructor.

The factory method does not have to be pure virtual. GoF describes two varieties: an abstract creator that forces every subclass to supply a product (what the example below does), and a concrete creator that provides a sensible default and lets subclasses override it only when they want something different.

Note: Two C++ specifics from GoF's implementation notes. First, never call a factory method from the creator's constructor — while the base part of the object is still being constructed the subclass override is not in place yet, so you silently get the base class's version, and if the factory method is pure virtual the program simply dies. Create the product lazily in an accessor instead. Second, a parameterized factory methodvirtual std::unique_ptr<Document> create(DocumentId) — lets one method build several kinds of product; an override typically handles the ids it cares about and delegates the rest back to the base implementation.

Structure

Structure of the Factory Method pattern Structure of the Factory Method pattern
Structure of the Factory Method pattern

Four participants forming two parallel hierarchies — creators on one side, products on the other, joined by a single dashed arrow:

  • Product — the interface of the object being created. Document in the example below.
  • ConcreteProduct — an implementation of that interface. HtmlDocument, MarkdownDocument.
  • Creator — declares the factory method returning a Product, and contains the operation that uses the product without knowing its class. Report, whose print() is that operation. GoF notes the Creator may also give the factory method a default implementation.
  • ConcreteCreator — overrides the factory method to return one particular ConcreteProduct. HtmlReport, MarkdownReport.

C++ example

A report that renders itself in whatever document format its subclass supplies.

#include <iostream>
#include <memory>
#include <string>
#include <vector>

// Product interface
class Document {
public:
    virtual ~Document() = default;
    virtual std::string heading(const std::string& text) const = 0;
    virtual std::string paragraph(const std::string& text) const = 0;
};

class HtmlDocument : public Document {
public:
    std::string heading(const std::string& t) const override { return "<h1>" + t + "</h1>"; }
    std::string paragraph(const std::string& t) const override { return "<p>" + t + "</p>"; }
};

class MarkdownDocument : public Document {
public:
    std::string heading(const std::string& t) const override { return "# " + t; }
    std::string paragraph(const std::string& t) const override { return t; }
};

// Creator: owns the workflow, not the choice of product.
class Report {
public:
    virtual ~Report() = default;

    // The factory method — subclasses decide the concrete Document.
    virtual std::unique_ptr<Document> createDocument() const = 0;

    void print(const std::string& title, const std::string& body) const {
        auto doc = createDocument();
        std::cout << doc->heading(title) << "\n";
        std::cout << doc->paragraph(body) << "\n";
    }
};

class HtmlReport : public Report {
public:
    std::unique_ptr<Document> createDocument() const override {
        return std::make_unique<HtmlDocument>();
    }
};

class MarkdownReport : public Report {
public:
    std::unique_ptr<Document> createDocument() const override {
        return std::make_unique<MarkdownDocument>();
    }
};

int main() {
    std::vector<std::unique_ptr<Report>> reports;
    reports.push_back(std::make_unique<HtmlReport>());
    reports.push_back(std::make_unique<MarkdownReport>());

    for (const auto& report : reports) {
        report->print("Q3 Sales", "Revenue is up 12%.");
        std::cout << "---\n";
    }
}
Output
<h1>Q3 Sales</h1>
<p>Revenue is up 12%.</p>
---
# Q3 Sales
Revenue is up 12%.
---

The print function was written once and never mentions HTML or Markdown, yet each report comes out in its own format.

When should you use it?

GoF's applicability list is three bullets long. Use Factory Method when:

  • A class cannot anticipate the class of objects it must create. A framework knows when a document is needed; only the application built on it knows which document.
  • A class wants its subclasses to specify the objects it creates. The workflow is fixed and inherited; the choice of product is the one thing left open.
  • A class delegates work to one of several helper subclasses, and you want the knowledge of which helper to use kept in one place. GoF's example is parallel hierarchies: each Figure creates the Manipulator that handles dragging it, so the pairing lives in a single overridden method rather than being scattered.

Pros and cons

Pros (GoF's consequences)

  • No application-specific classes get bound into your code. The workflow deals only with the Product interface, so it works with any ConcreteProduct anyone writes later, including ones that did not exist when it was compiled.
  • It provides a hook for subclasses. Creating an object through a factory method is always more flexible than creating it directly, because a subclass can substitute an extended version.
  • It connects parallel class hierarchies. When a class delegates part of its job to a companion class, the factory method is the single place that records which companion belongs to which class.

Cons

  • Clients may have to subclass the creator just to get one product — GoF's own stated disadvantage. That is fine if you were subclassing it anyway, and an extra point of evolution to maintain if you were not.
  • Class count grows: one creator subclass per product, even for trivial products.
  • The indirection is invisible in a stack trace — readers must find the subclass to know what was actually built.
  • In C++ the flexibility stops at the binary: swapping in a different concrete product still means a recompile, unless you go further and load creators from plugins at run time.

Tip: GoF's own workaround for the class explosion is a template creator — template <class TheProduct> class StandardCreator : public Creator, whose factory method just returns new TheProduct. The client supplies the product type and writes no subclass at all. In modern C++ a std::function<std::unique_ptr<Document>()> handed to a plain Report is the same idea with less ceremony.

How to remember it

Memory hook: "Leave a blank in the recipe and let the subclass fill it in." GoF's alternative name — Virtual Constructor — is the whole pattern in two words. The sibling test: Factory Method is one product, decided by subclasses; Abstract Factory is a whole matching family per factory object.

  • Abstract Factory — usually implemented out of factory methods: one per product in the family.
  • Template Method — GoF notes factory methods are normally called from inside a template method, which is exactly what print() is here: a fixed algorithm with one subclass-supplied step.
  • Prototype — the alternative that needs no Creator subclass at all, since an existing object copies itself. The trade: prototypes usually need an Initialize operation on the product to set the copy's state, which Factory Method never requires.