Design Patterns interview question · Most asked
Explain the Factory Method pattern and how it differs from a simple factory.
Summary
Factory Method lets subclasses decide which product to create by overriding a creation method that a shared algorithm calls. A simple factory is one function or class with a conditional that returns the right object; it isn't a GoF pattern but solves the same 'who decides the class' problem without subclassing.
Longer Answer
In Factory Method, the creator's algorithm (export()) calls create_formatter(); CsvReport and JsonReport override it. The algorithm only depends on the product interface, so new products need no changes to it. It suits frameworks where users extend a base class.
A simple factory (create_formatter("csv"), or a dictionary from names to classes) is more common in application code. With first-class functions, passing the product or a function that creates it is often simplest.
Code Example
class Csv:
def format(self, row):
return ",".join(row)
class Pipe:
def format(self, row):
return " | ".join(row)
class Report:
def create_formatter(self): # the factory method
raise NotImplementedError
def export(self, row):
return self.create_formatter().format(row)
class CsvReport(Report):
def create_formatter(self):
return Csv()
class PipeReport(Report):
def create_formatter(self):
return Pipe()
for report in [CsvReport(), PipeReport()]:
print(report.export(["1", "Ada"]))
interface Formatter { format(row: string[]): string; }
class Csv implements Formatter { format(row: string[]) { return row.join(","); } }
class Pipe implements Formatter { format(row: string[]) { return row.join(" | "); } }
abstract class Report {
protected abstract createFormatter(): Formatter; // the factory method
export(row: string[]) { return this.createFormatter().format(row); }
}
class CsvReport extends Report { protected createFormatter() { return new Csv(); } }
class PipeReport extends Report { protected createFormatter() { return new Pipe(); } }
for (const report of [new CsvReport(), new PipeReport()]) console.log(report.export(["1", "Ada"]));
import java.util.List;
public class Main {
public static void main(String[] args) {
for (Report report : List.of(new CsvReport(), new PipeReport())) {
System.out.println(report.export(List.of("1", "Ada")));
}
}
}
interface Formatter { String format(List<String> row); }
class Csv implements Formatter { public String format(List<String> row) { return String.join(",", row); } }
class Pipe implements Formatter { public String format(List<String> row) { return String.join(" | ", row); } }
abstract class Report {
protected abstract Formatter createFormatter(); // the factory method
String export(List<String> row) { return createFormatter().format(row); }
}
class CsvReport extends Report { protected Formatter createFormatter() { return new Csv(); } }
class PipeReport extends Report { protected Formatter createFormatter() { return new Pipe(); } }
<?php
interface Formatter { public function format(array $row): string; }
class Csv implements Formatter { public function format(array $row): string { return implode(",", $row); } }
class Pipe implements Formatter { public function format(array $row): string { return implode(" | ", $row); } }
abstract class Report {
abstract protected function createFormatter(): Formatter; // the factory method
public function export(array $row): string { return $this->createFormatter()->format($row); }
}
class CsvReport extends Report { protected function createFormatter(): Formatter { return new Csv(); } }
class PipeReport extends Report { protected function createFormatter(): Formatter { return new Pipe(); } }
foreach ([new CsvReport(), new PipeReport()] as $report) echo $report->export(["1", "Ada"]), "\n";
Key Points
- Creator calls an overridable creation method.
- Subclasses choose the concrete product.
- Simple factory = one creating function/lookup.
- Java's Collection.iterator() is a factory method.
Deep dive: Design Patterns, Explained Simply: Factory Method
Explanation
What interviewers look for
Correct roles (creator, factory method, product) and the distinction from a simple factory.
Follow-up questions
- When would you prefer a dictionary of constructors?
- How does Factory Method support Open/Closed?
More most-asked Design Patterns questions
- How do you implement a Singleton, and why is it often considered an anti-pattern?
- Explain the SOLID principles.
- What is a design pattern, and why are they useful?
- What is the difference between dependency inversion, dependency injection and inversion of control?
- Why is composition often preferred over inheritance?
- What is dependency injection, and what forms does it take?
- What problem does the Builder pattern solve? Show an example.
- What is the Adapter pattern? Give an example.