What is the difference between Strategy and Template Method patterns…, if there is any?

In our Spring book, we discuss about transaction management mechanisms available in the Spring Framework, namely declarative and programmatic transactions. It is further explained inside programmatic transaction demarcation section, that how programmatic transaction can be achieved using different methods. One of the ways programmatic transaction can be achieved is, using TransactionTemplate utility class provided by Spring itself. It is based on Template Method pattern which constantly emerges over several different parts of the Spring Framework to encapsulate steps of a recurring operation, such as data access, transaction management, REST or JMS communication logic etc. In that case, main transaction demarcation logic is fixed within the specific template method, but varying steps can be given into it later on, so that specifics of the algorithm can be customized by the calling body. In our case transactional code block which needs to be run within an active transaction is given as method parameter.

TransactionTemplate tt = new TransactionTemplate(transactionManager);
tt.execute(new TransactionCallbackWithoutResult() {
        public void doInTransaction(TransactionStatus status) {
                entityManager.persist(pet);
        }
});

Recently, one of our book readers asked about whether mentioning about TransactionTemplate as an example of Template Method is really correct. He asked that; shouldn’t we call it as Strategy instead. Well, actually both Strategy and Template Method patterns are very similar in behavioural aspect. Indeed, we can call them as cousins with some slightly different characteristics. They both try to encapsulate an algorithm. However, they varies in how that encapsulation is achieved.


Strategy pattern encapsulates the algorithm using object composition or delegation. Subject depends on Strategy interface, and a concrete implementation of the Strategy is chosen and invoked based on decisions made at runtime. That way specific algorithm, which will be executed, can be determined and changed dynamically. Context information of the client environment, which might be consulted at during execution of the algorithm, is usually passed in as method argument in the Strategy pattern.

public class AuthenticationProvider {
	private UserService userService;
	
	public AuthenticationProvider(UserService userService) {
		this.userService = userService;
	}

	public boolean authenticate(String username, String password) {
		User user = userService.loadUserByUsername(username);
		return user != null && user.getPassword().equals(password);
	}
}

public interface UserService {
	public User loadUserByUsername(String username);
}

In the above code sample, AuthenticationProvider depends on UserService in order to obtain User object through it. UserSerice, an interface, is in role of Strategy here, and it may have several concrete implementations, each of which queries User by username from different user realms. Any of those concrete implementations can be injected into AuthenticationProvider at runtime.

 

On the other hand, Template Method pattern handles encapsulation of the algorithm and selection of it at compile time, usually based on inheritance. It fixes main steps of algorithm in a base class, called as Template Method class, and expects varying steps to be provided by the specific subclass which extends from the Template method base class. Therefore, algorithm selection is finished long before application state becomes running.

public abstract class QueryTemplate {

	private DataSource dataSource;

	public void setDataSource(DataSource dataSource) {
		this.dataSource = dataSource;
	}
 
	public final List execute() {
		Connection connection = null;
		PreparedStatement statement = null;
		try {
			connection = dataSource.getConnection();
			String sql = getSql();
			statement = connection.prepareStatement(sql);
			Object[] args = getArgs();
			for(int i = 0; i < args.length; i++) {
				statement.setObject(i+1, args[i]);
			}
			ResultSet resultSet = statement.executeQuery();
			List resultList = new ArrayList();
			while (resultSet.next()) {
				T record = process(resultSet);
				resultList.add(record);
			}
			return resultList;
		} catch (SQLException e) {
			throw new RuntimeException(e);
		} finally {
			if (statement != null)
				try {
					statement.close();
				} catch (SQLException e) {}
			if (connection != null)
				try {
					connection.close();
				} catch (SQLException e) {}
		}
	}

	protected abstract String getSql();
	protected abstract Object[] getArgs();
	protected abstract T process(ResultSet resultSet) throws SQLException ;
}

In the above code sample, QueryTemplate is a base class in which execute() method is implemented along with three other abstract methods which are called by the execute() method at specific steps during query execution process. Sub classes extending QueryTemplate override those abstract methods in order to implement expected behaviours within them. Clients don’t need to know exact sub type during query execution, they simply depend on QueryTemplate to perform their task.

Inheriting Template method class is not the most effective way from a framework perspective to provide varying parts. In Java environment, it cannot be feasible every time as well, especially the class which needs to extend from Template Method class is already extending from another class. We hit against multiple inheritance limitation at that case. Instead, frameworks follow another way to feed Template Method with those varying steps; as method input arguments.

public class QueryTemplate {

	private DataSource dataSource;

	public void setDataSource(DataSource dataSource) {
		this.dataSource = dataSource;
	}

	public final List execute(String sql, RowExtractor rowExtractor, Object...args) {
		Connection connection = null;
		PreparedStatement statement = null;
		try {
			connection = dataSource.getConnection();
			statement = connection.prepareStatement(sql);
			for(int i = 0; i < args.length; i++) {
				statement.setObject(i+1, args[i]);
			}
			ResultSet resultSet = statement.executeQuery();
			List resultList = new ArrayList();
			while (resultSet.next()) {
				T record = rowExtractor.process(resultSet);
				resultList.add(record);
			}
			return resultList;
		} catch (SQLException e) {
			throw new RuntimeException(e);
		} finally {
			if (statement != null)
				try {
					statement.close();
				} catch (SQLException e) {}
			if (connection != null)
				try {
					connection.close();
				} catch (SQLException e) {}
		}
	}

	public static interface RowExtractor {
		public T process(ResultSet rs);
	}
}

That code sample shows variation in Template Method mentioned previously. QueryTemplate is concrete in this case, and RowExtractor is interface which declares a method to process each row in the ResultSet return from the query executed. Both query to be executed, query parameters if there exists any, and rowExtractor object are given as method parameters to execute method of QueryTemplate. That way, application code doesn’t need to extend from Template Method class over and over again. It just calls the method in order to execute the algorithm, and passes varying steps as method arguments into it.

If the varying parts are code blocks that need to be executed at a specific point in the algorithm, the only possible way prior to Java 8 was anonymous classes. Some contextual information, like TransactionStatus in our TransactionTemplate example, can be passed in as method parameters of anonymous class similar to Strategy pattern as well. Probably, this variation in the implementation of the Template Method pattern causes some people to think that it more resembles to the Strategy pattern.