skipnothing/Design Patterns

Factory Method

A planRoute method opens with new Truck(), and so does the mobile endpoint, the admin re-run button, and the retry job. The day sea freight arrives, every one of those files has to learn the word Ship.

  • ▸Scatter new Truck() across callers and a new vehicle edits them all; behind one overridable method, it edits none.
  • ▸The win isn't deleting new; it's moving the one line that picks the class so callers name none.
  • ▸Collection.iterator() ships this in the JDK: each collection returns its own iterator, your loop never names the class.
01

The hardwired new

A planDelivery method starts innocent. It works out a route and books the vehicle in one line:

class Logistics {
  planDelivery(order) {
    const truck = new Truck();   // the one line that names a class
    truck.load(order);
    return truck.route(order.from, order.to);
  }
}

That new Truck() looks harmless. The trouble is it isn't alone. The mobile endpoint books a truck. The admin 're-run delivery' button books a truck. A nightly retry job books a truck. Each one wrote new Truck() for itself.

Then the company adds sea freight. Now every place that built a truck sometimes needs a ship instead, so each grows the same branch:

const vehicle = order.bySea ? new Ship() : new Truck();

The decision 'which class do I build' is now copy-pasted into every caller, and the day air freight arrives you edit all of them again. The actual work, picking a vehicle for an order, is one decision. The code has scattered that one decision across every file that ever needed a vehicle. Each caller is welded to the concrete classes instead of to the job it wanted: get a vehicle and use it.

ONE DECISION, COPIED INTO EVERY CALLER

Keep going, sign up to unlock the rest

4 more parts in this topic, plus 18+ more topics in Design Patterns.

Sign up, it's freeSee the full Design Patterns
Creational Patterns0/4#11 Facade
#13 Abstract Factory