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).
A conditional construction block the agent must scan to know which collaborator gets built for a given type code. Adding a variant requires the agent to enumerate every such construction site in scope and add a branch — Shotgun Surgery in static reasoning.
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.
Each subclass's Factory Method is locally verifiable; the base algorithm has no construction-conditional for the agent to load. The agent's per-edit budget on a variant addition is one new subclass, not N edits to construction sites.
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.
Construction conditionals couple the base class to the full variant taxonomy; the agent must hold every variant in working memory to verify any edit to the base. Cross-variant invariants (e.g., that every parser implements `.parse`) are not statically enforceable when construction goes through type-code strings.
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.
Factory Method spreads creation across the inheritance hierarchy; the agent must traverse subclasses to know which concrete type a base-class call produces. Static call-graph analysis loses precision on the return type of `createParser()`.
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.
Adding a new variant is one new subclass that overrides the factory hook; the base algorithm reads one virtual call instead of branching on a type code, and the algorithm's body stays constant in size as variants are added.
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`.
A hierarchy with one trivial Factory Method per subclass forces the agent to load the inheritance chain to know what a single base-class call returns. The pattern's context-cost gain materializes only when each Factory Method does non-trivial work — otherwise the indirection adds cost without proportional clarity.