Template Pattern vs Composite Approach (OOP)

This is based on an answer I wrote in response to a code review post.

You have opted for the template pattern (predominantly at least):

There are costs and benefits with your approach, which as I understand is essentially this.

Abstract class: Vehicle from which the following are derived:

  1. Compact
  2. Luxury
  3. Truck
  4. Wagon

And the fields of the abstract parent class:

  1. Engine Serial Number
  2. Brand
  3. Year
  4. Price

The Template pattern vs Composition approach – pros and cons

(i) Template good when adding more sub-classes without much work

(ii) Template bad if you want to change base class in future and this change does not apply to all sub-classes

The template pattern solution which you’ve gone for is great – especially if you need to add further vehicles – you can do so relatively easy – but only so long as they match exactly with the public interface of the Vehicle abstract class. In other words, all subclasses must: have an engine serial number, a brand, a year and a price. If not, then you cannot readily subclass from the Vehicle class. If you do, then you’re inviting problems for developers down the line, and for those maintaining your code base – you’ll be violating the Liskov substitution principle. This principle suggests to all future developers that they are entitled to believe that Wagon/Truck/LuxuryCar/CompactCar acts like a Vehicle if it is subclassed from the abstract vehicle class. In other words, the risk you take is that the parent class applies to all subclasses.

(iii) Elaboration on the problems associated with changing the base-class

If later in the future, vehicles need an engine number which requires more sophistication (not an integer but a more complex type), but you still want the sub-classes to retain the integer type for their respective engine numbers then you’re kind of in a tight spot. You’ve already defined the super class. But you want the sub-class to be different. You want to violate the Liskov-substitution principle. With inheritance you can’t do this. With a composition based approach you can – because a Wagon/Truck/LuxuryCar/CompactCar is not a Vehicle. This means that the abstract base class can change it’s interface, but you don’t have to make subsequent changes where the derived class are called – but you will have to make changes to the relevant implementations within the derived classes. I hope this is making sense.

You could use the composition approach with a common interface between all types. Then in the future you could resort to an abstract parent class when you have more complete information. So do you wait, or do you bite the bullet and pour the concrete foundations now, making it difficult to change later?

Summary

  • If you go for the composition approach you’ll be repeating yourself may times over because you cannot simply automatically delegate/fwd to the abstract parent class.
  • But then again you’ll have freedom because you’re not locked into the “parent class” interface and any subsequent changes to the “parent class” need not affect the interface of the “sub-classes” (though it will affect their implementations).
  • There are pros and cons to both approaches – just be aware of them.
Written on September 13, 2017