Template method pattern

Template method pattern

software_development

The template method pattern defines the structure of an algorithm creating a parent class that holds the main steps, leaving its subclasses to implement possible variations.

Example

We have two games, Chess and Draughts, with these classes:


public class ChessGame {
	private List players;

	public void play(){
		while(!isGameOver()){
			Player turnPlayer = getPlayerOfThisTurn();
			Move move;

			do{
				move = turnPlayer.performMove();
			} while(!isMoveValid(move))
		}
	}

	private boolean isGameOver(){
		// check if there is a checkmate
	}

	private Player getPlayerOfThisTurn(){
		// get next player
	}

	private Move performMove(){
		// move a piece accordingly to his type
	}

	private boolean isMoveValid(Move move){
		// check if the piece has been move accordingly to his type
	}
}

public class DraughtsGame{
	private List players;

	public void play(){
		while(!isGameOver()){
			Player turnPlayer = getPlayerOfThisTurn();
			Move move;

			do{
				move = turnPlayer.performMove();
			} while(!isMoveValid(move))
		}
	}

	private boolean isGameOver(){
		// check if the players have any pieces left
	}

	private Player getPlayerOfThisTurn(){
		// get next player
	}

	private Move performMove(){
		// move a piece or capture one
	}

	private boolean isMoveValid(Move move){
		// check if the movement priority has been followed
	}
}

Looking close to the two games we can see that the game main structure is the same, the only things that change are the implementation of the isGameOver, performMove and isMoveValid methods. We can remove the duplicate code creating a generic Game class.


public abstract class Game{
	protected List players;

	public void play(){
		while(!isGameOver()){
			Player turnPlayer = getPlayerOfThisTurn();
			Move move;

			do{
				move = turnPlayer.performMove();
			} while(!isMoveValid(move))
		}
	}

	private Player getPlayerOfThisTurn(){
		// get next player
	}

	protected abstract boolean isGameOver();
	protected abstract Move performMove();
protected abstract boolean isMoveValid(Move move);
}

On the Game class the play method is left intact, same for the getPlayerOfThisTurn. The other methods are being turned to abstract, because every class that inherits from Game implements it differently. Let’s see how Chess and Draughts are shaped now:


public class ChessGame extends Game {
	protected boolean isGameOver(){
		// check if there is a checkmate
	}

	protected Move performMove(){
		// move a piece accordingly to his type
	}

	protected boolean isMoveValid(Move move){
		// check if the piece has been move accordingly to his type
	}
}

public class DraughtsGame extends Game{

	protected boolean isGameOver(){
		// check if the players have any pieces left
	}

	protected Move performMove(){
		// move a piece or capture one
	}

	protected boolean isMoveValid(Move move){
		// check if the movement priority has been followed
	}
}

As you can see, the Game class holds the main steps of the algorithm, while the Chess and Draughts classes contain only the variations steps.

Related News