Card 07/ 09

GotchaDifficulty: Advanced1 min

A Factory Method With Only One Product

A creator hierarchy around a single class adds two classes and protects nothing.

A factory method earns its place when there is a second product to choose between, and without one it is two extra classes and an indirection protecting against a change nobody expects. It is a common result of learning the pattern: a creator, a concrete creator and a product interface appear around one class that the code could create directly. This card shows the shape and the check that catches it.

One product, with and without the pattern

With the patterna hierarchy with one member

py
class ReportCreator(ABC):
    @abstractmethod
    def create_formatter(self) -> Formatter: ...

    def run(self, rows):
        return self.create_formatter().format(rows)

class CsvReportCreator(ReportCreator):
    def create_formatter(self) -> Formatter:
        return CsvFormatter()

CsvFormatter is the only formatter, and CsvReportCreator the only creator.

Without itwhat the code does

py
class Report:
    def run(self, rows):
        return CsvFormatter().format(rows)

Same behaviour, one class, and the reader sees the formatter on the line that uses it.

The trap is that the version with the pattern looks more professional, and it does make one change cheaper: adding a second formatter. If that change never comes, it has cost two classes, a Formatter interface, and a reader's time opening each to find there was nothing to decide.

The check is to name the second product. If you can, and it is planned, the pattern is reasonable. If you cannot, write the plain version: when a second formatter does arrive, extracting a factory method from run is a few minutes' work, and you will then know which part varies.

The same check applies to the subclass itself. If the only thing a subclass would ever change is the class created, passing the class in, as Python does with a callable, is the smaller design.