38

Replace Subclass with Delegate


Goal

Behavior that varied via inheritance now varies via a delegate object that implements the variant interface.

Before the refactoring
class Booking { /* ... */ }
class PremiumBooking extends Booking {
  /* overrides several methods */
}
After the refactoring
class Booking {
  type; // 'standard' | premium delegate
  charge() { return this.type.charge(this); }
}
Savings

Variants can be combined or swapped at runtime; Liskov violations vanish; the hierarchy tree flattens.

Note

Composition is more verbose at construction sites — accept the verbosity in exchange for the flexibility.