The Composite Reuse Principle (CRP)

Favor delegation over inheritance as a reuse mechanism

Many design patterns are based on delegation rather than inheritance as a reuse mechanism. Delegation can be seen as a reuse mechanism at the object level, while inheritance is a reuse mechanism at the class level.

For example, suppose an Employee class has a method for computing the employee's annual bonus:

class Employee {
   Money computeBonus() { /* skimpy default bonus */ }
   // etc.
}

Different subclasses of Employee: Manager, Programmer, Secretary, etc. may want to override this method to reflect the fact that some types of employees (managers) get more generous bonuses than others (secretaries and programmers):

class Manager extends Employee {
   Money computeBonus() { /* gerenous bonus */ }
   // etc.
}

There are several problems with this solution.

1. All programmers get the same bonus. What if we wanted to vary the bonus computation among programmers? Would we need to introduce a special subclass of Programmer?

class SeniorProgrammer extends Programmer {
   Money computeBonus() { /* gerenous bonus */ }
   // etc.
}

Note also that this leads to code duplication.

2. What if we wanted to change the bonus computation for a particular employee? For example, what if we wanted to promote Smith from programmer to senior programmer? Would this require us to recompile any code?

3. What if we decided to give all programmers the same generous bonus that managers get? What changes would we need to make? Should "generous bonus" become the new default algorithm that is overridden in the Secretary class with the skimpy bonus algorithm? Should we copy and paste the "generous bonus" algorithm from manager to Programmer?

Alternatively, we can use the Strategy pattern and introduce a separate hierarchy of bonus calculators:

Now different employees can have different bonus calculators, regardless of the class they instantiate. Even better, the bonus calculator used by a particular employee can be changed dynamically.

When we begin to override inherited methods, the is-a semantics implied by the extends relationship begins to break down. At what point does inheritance become a nuisance? At what point does the behavior of a manager diverge from the default behavior of an employee that we can no longer say that a manager is an employee?