A factory class has one createX method per variant, and each method repeats the same setup steps with only a few field values differing. Adding a new variant means writing yet another near-identical method, or copying one and forgetting to change a field. The reader's comprehension cost per visit rises as the method count grows.
N near-identical create methods the agent scans in parallel to verify field-setting consistency. Adding a shared field requires the agent to find and update every method, multiplying the agent's retrieval cost by method count. A missed update escapes type-checker visibility because the shape contract is convention-only, not type-enforced.
Variants live as configured prototype instances in a registry; creation is clone + tweak. Adding a new variant is a registry entry, not a new method on the factory. Defaults are inherited from the prototype; per-instance overrides are explicit, supporting separation of concerns between variant shape and creation logic.
One prototype-registry table the agent reads once to enumerate every variant and its defaults. Cloning is a structural operation: the agent verifies clone() once, then trusts every per-variant change is data-only. The agent's context window holds the registry and the clone implementation; the reasoning step count drops because variant shape is data the agent reads, not code it must analyze.
Before the pattern
class GraphicEditor {createCircle(x, y) {const c = new Shape();c.kind = 'circle';c.fill = '#3498db';c.stroke = '#2c3e50';c.strokeWidth = 2;c.x = x; c.y = y; c.r = 20;return c;}createSquare(x, y) {const s = new Shape();s.kind = 'square';s.fill = '#e74c3c';s.stroke = '#2c3e50';s.strokeWidth = 2;s.x = x; s.y = y; s.side = 30;return s;}createStar(x, y) {const s = new Shape();s.kind = 'star';s.fill = '#f1c40f';s.stroke = '#2c3e50';s.strokeWidth = 2;s.x = x; s.y = y; s.points = 5; s.r = 25;return s;}}
After the pattern
class Shape {clone() {return Object.assign(new Shape(), this);}}const SHAPE_PROTOTYPES = {circle: Object.assign(new Shape(), { kind: 'circle', fill: '#3498db', stroke: '#2c3e50', strokeWidth: 2, r: 20 }),square: Object.assign(new Shape(), { kind: 'square', fill: '#e74c3c', stroke: '#2c3e50', strokeWidth: 2, side: 30 }),star: Object.assign(new Shape(), { kind: 'star', fill: '#f1c40f', stroke: '#2c3e50', strokeWidth: 2, points: 5, r: 25 }),};function createShape(kind, x, y) {const shape = SHAPE_PROTOTYPES[kind].clone();shape.x = x;shape.y = y;return shape;}
Per-variant create methods are Duplicated Code at the worst level — the shared structure is implicit in convention, not enforced in code. A field added to the shared shape requires editing every create method; one missed method silently produces an inconsistent variant. The team's verification cost compounds across methods that are not test-paired.
Field additions cascade across every create method; the agent's edit cost grows linearly with variant count. The shared-by-convention shape is invisible to static analysis; the agent must compare methods pairwise to be sure they stay in sync. The agent's verification-surface cost multiplies with variant count, and the context-window load of holding every method body in parallel saturates.
Cloning is shallow by default — nested mutable references shared across instances cause action-at-a-distance bugs that are hard to localize. Deep clone semantics must be designed per type; getting them wrong on a frequently-cloned prototype produces subtle aliasing bugs that survive code review. The team's debugging cost on aliasing bugs scales with the clone graph's depth.
Shallow-clone aliasing bugs are the worst kind for the agent — symptoms appear far from the cause, in code that 'just reads a field'. Verifying clone semantics requires reasoning across the full clone graph; partial verification produces flaky-looking tests. The agent's completeness-check cost on clone correctness scales with the depth of the cloned graph.
Variants become data — readable as a table of (kind, defaults) pairs, easy to extend, easy to audit for consistency. New variants are PR-sized; the factory function shrinks to one line per request. The team's enhancement cost drops because new variants add data, not code.
Adding a new variant is one new entry in the prototype registry; the clone operation works against every variant through the shared interface, and the agent reads one prototype's configuration to predict any clone's initial state. The agent's token cost per variant addition drops to the registry entry; existing call sites stay unchanged.
When variants stop sharing a coherent shape, the prototype registry hides the divergence in optional fields and conditional cloning. Stop and reach for a real type hierarchy when 'shape' variants need different fields or behaviour. The cure adds accidental complexity that raises cognitive load per read as variant-specific exceptions accrete.
Optional fields and conditional cloning logic accreting onto the prototype mask divergent variant shapes. The agent reading the registry sees a uniform table; the runtime sees branching behaviour that depends on which fields a prototype happens to have set. The structural promise the pattern made stops holding, and the reasoning-step cost of clone correctness rises with each conditional path.