A method conditionally constructs a collaborator based on a type code carried by the caller. The conditional grows wider with every new variant; each variant's construction details leak into the shared method body; the method changes for two unrelated reasons (algorithm and variant-set).
The base class declares an abstract Factory Method and uses the result polymorphically. Each subclass owns the creation knowledge for its variant; the base class's algorithm is conditional-free and stable.
Before the refactoring
// Branching on a type code to decide which collaborator to construct.class DocumentReader {constructor(format) {this.format = format;}read(text) {let parser;if (this.format === 'xml') {parser = new XmlParser();} else if (this.format === 'json') {parser = new JsonParser();} else if (this.format === 'csv') {parser = new CsvParser();} else {throw new Error(`unsupported format ${this.format}`);}return parser.parse(text);}}
After the refactoring
// Each subclass owns its createParser primitive; the base class is conditional-free.class DocumentReader {read(text) {return this.createParser().parse(text);}createParser() {throw new Error('abstract: subclasses must implement createParser');}}class XmlReader extends DocumentReader {createParser() {return new XmlParser();}}class JsonReader extends DocumentReader {createParser() {return new JsonParser();}}class CsvReader extends DocumentReader {createParser() {return new CsvParser();}}
Type-code-driven construction is Shotgun Surgery waiting to happen — a new variant requires editing every conditional that branches on the type. The variant-set becomes a cross-cutting concern duplicated everywhere a related decision is made.
Factory Method requires a class hierarchy; what was one class becomes a base plus subclasses. For variant sets that are stable and small (two or three formats that have never changed), a conditional may be cheaper than the inheritance ceremony.
The base class's algorithm is finalized; new variants land as new subclasses with no edits to the base. Per-variant creation is locally readable and locally testable; the algorithm's correctness is verified once.
A Factory Method whose only job is `return new X()` per subclass is constructor syntax with extra steps. The pattern pays when creation involves real choices — caching, parameter shaping, conditional sub-collaborators — not when it is a one-line `new`.