Template pattern v.s. Interface pattern

As a library programmer, the decision between using templates or using inheritance may be a difficult decision. Everyone wants their libraries to be generic. Which pattern is better?

Template pattern
Templates allow you to write code that does the same thing on unrelated types. For example, in C++, std::sort in STL is a function template. It allow us to sort anything that can be compared using the less-than operator and swapped using std::swap (another function template)

Interface pattern
When you call a polymorphic method, the final overrider of the method is called, even if you call the method by using an expression of a base class as the static type. A class can be used as an interface if it does not contain any non-polymorphic methods (excluding constructors) or public/protected fields. An interface may contain public/protected properties if the underlying method is polymorphic. If a language supports “polymorphic field”, that is, a field can be overriden with a property with polymorphic behaviour, you can also include a field in an interface. In short, an interface is a class that its public interface does not depend on any of its implementation.

A comparison
Templates can be written using whatever style you want but there is a number of limitation when using the interface pattern:

  • You must pass the object by pointer or by reference to the function written by its interface, but not by copy. In languages that support dynamically determining the type of an object (the “dynamic” type), it’s not a problem since you can copy that object inside the function.
  • The classes accepted by the function must be inherited from the interface. That is, they must share the same class hierarchy. Consider the following code in C++:
    class vehicle {
    public:
    	virtual ~vehicle();
    	virtual void accelerate() = 0;
    	virtual void decelerate() = 0;
    };
    

    This is an abstract base class without implementation of vehicle::accelerate() and vehicle::decelerate(). Code can be written using this interface, regardless of the actual implementation of vehicle::accelerate() and vehicle::decelerate(). However, given another class below:

    class car {
    	virtual void accelerate();
    	virtual void decelerate();
    	virtual ~car();
    };
    

    You can’t use code written to the vehicle interface. You must multiply inherit from car (to use its implementation) and vehicle (to use its interface). Even worse, if car::accelerate() and car::decelerate weren’t made virtual, you cannot use the interface at all. In languages that do not support multiple inheritance, you can’t use the interface at all.

Template itself is good, but made worse by C++ implementations.

Leave a Reply

Your email address will not be published. Required fields are marked *