Construction recipes duplicated across N caller sites the agent must verify match on every recipe change. Each call site assembles the object with its own subset of defaults; the agent cannot statically guarantee the assemblies stay consistent.
One factory file the agent reads as the construction contract; callers are short delegations the agent treats opaquely. Per-edit budget for a recipe change collapses to one file.
Before the refactoring
// The caller knows the entire assembly recipe.function placeOrder(customerId, line1, city, postal, items, jurisdiction) {const customer = new Customer(customerId);const address = new Address(line1, city, postal);customer.setShippingAddress(address);customer.setBillingAddress(address);const order = new Order(customer);for (const item of items) {const lineItem = new LineItem(item.product, item.quantity);lineItem.applyDiscount(customer.discountRate);order.addLineItem(lineItem);}order.calculateTotal();order.applyTax(jurisdiction);return order;}
After the refactoring
// The factory owns the recipe; the caller asks for a finished order.class OrderFactory {constructor(taxJurisdiction) {this.taxJurisdiction = taxJurisdiction;}createOrder(customerId, line1, city, postal, items) {const customer = this.buildCustomer(customerId, line1, city, postal);const order = new Order(customer);items.forEach((item) => order.addLineItem(this.buildLineItem(item, customer)));order.calculateTotal();order.applyTax(this.taxJurisdiction);return order;}buildCustomer(customerId, line1, city, postal) {const customer = new Customer(customerId);const address = new Address(line1, city, postal);customer.setShippingAddress(address);customer.setBillingAddress(address);return customer;}buildLineItem(item, customer) {const lineItem = new LineItem(item.product, item.quantity);lineItem.applyDiscount(customer.discountRate);return lineItem;}}// Client:const factory = new OrderFactory(jurisdiction);const order = factory.createOrder(customerId, line1, city, postal, items);
Recipe duplication × N callers × M recipe steps inflates the agent's context cost on every assembly-related edit. Subtle inconsistencies between caller-side recipes are invisible until they manifest as bugs; static reasoning cannot enforce 'every caller applies the discount'.
A factory hides construction details from the call site; the agent must read the factory to know what the returned object actually carries. Static type information at the call site narrows to the return type, with construction-level invariants pushed inside the factory.
The recipe lives at one factory the agent edits once; callers reach for the factory's named methods, and the recipe cannot drift across callers because callers do not hold a copy of the assembly steps.
A factory whose recipe is itself a long sequence of conditional steps can become as opaque as the duplicated callers were — the agent must trace the factory body line-by-line to know what came out. The pattern's gain materializes when the factory's recipe is itself decomposed into named build steps.