Patterns I Hate #2: Template Method


In the first episode of this series I explored the Singleton pattern and why it sucks. In this episode, I take aim at the Template Method pattern.

To refresh your memory, the Template Method pattern is when you encapsulate the outline of an algorithm or lifecycle in an abstract class, but define certain specific steps as abstract methods. This class then forms a “template” that others can subclass, only supplying the details that are different.

So, you might have a template class and subclasses like this:

public abstract class ConnectionPool {

  // Public API
  public Connection obtain() { ... }
  public void release(Connection conn) { ... }

  // template methods
  protected abstract Connection createConnection();
  protected abstract boolean isAlive(Connection connection);
  protected abstract void closeConnection(Connection connection);

In this API, the ConnectionPool has public methods for users to obtain and release connections as they use them. The ConnectionPool maintains a pool of connections, but creates, closes, and verifies the health of the Connections via the template methods. Framework users would subclass ConnectionPool and add logic to create connections in a system-specific way.

Why is Template Method Evil?

  1. Communicates intent poorly – The template method pattern is often used as part of the effective API in some mini-framework where the framework user is expected to subclass the template class. My experience has been that it is difficult to communicate that usage intent to users of the framework. Often the template class has some non-private methods that are exposed for use by the framework but are not intended to be used by the framework user, some that are intended to be overridden, and some that are both. Also, you may need to say whether the super’s version of the method can, should, or must be called. Communicating all that clearly is impossible in an API of any complexity.
  2. Difficult to compose functionality – When inheritance is used as the way to add new functionality, it becomes impossible to add functionality in more than one axis at the same time without defining more and more classes. So, say you have a ConnectionPool and you start by having an OracleConnectionPool and DB2ConnectionPool and so on. But then you also need the ability to create XAConnections sometimes. So you then need to create OracleXAConnectionPool and DB2XAConnectionPool and so on. The per-DB pools share some functionality and the XA pools share functionality but can’t inherit from both. This typically leads to a lot of duplication and an explosion in implementations.
  3. Difficult to comprehend program flow – In my experience it takes very few levels of template methods and inheritance to make debugging or understand the sequence of method calls difficult (as few as 2 or 3). When template methods are really pushed (lots of abstract methods at multiple levels), it can become painful to debug this kind of a system.
  4. Difficult to maintain – Having maintained a couple chunks of code that made extensive use of the template method, it can be challenging. This kind of system can rapidly become fragile. Changes at any one level can disturb operation above or below that level in the template methods. There is often a feeling of unpredictability when adding new functionality as it difficult to predict how behavior will change in all cases. You often also tend to build finer and finer tweaks by splitting the algorithmic parts of the template class and inserting more layers, thus exacerbating the problem.

What’s the alternative?

Usually, the best way to address the addition of functionality in orthogonal domains under a template class is to define an interface for each kind of functionality and inject an instance for each. Typically these interfaces are factories and strategies. You can then mix and match each piece separately and also insert interceptors to handle functionality like logging, pooling, caching, etc. This lets you assemble a particular instance of the main class with exactly the mixture of pluggable elements to satisfy your needs. In general, I find this to be easier to understand, more flexible, and more maintainable.

For the example above, you might instead change this to:

public class ConnectionPool {
  private ConnectionFactory connFactory;
  public ConnectionPool(ConnectionFactory factory, EvictionPolicy policy, ...) {
    // store subcomponent instances

  // Public API is the same, template methods are gone

// Move template methods into a pluggable factory
public interface ConnectionFactory {
  Connection createConnection();
  boolean isAlive(Connection connection);
  void closeConnection(Connection connection);

Thanks for reading. After Singleton and Template Method, my level of hate goes down quite a bit, so I suspect the next victims selections for this series will be more of the love/hate variety.

Comments are closed.