Template method pattern

This is an old revision of this page, as edited by Supadawg (talk | contribs) at 14:43, 14 July 2006 (Example in C++: rm sig). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.

In software engineering, the template method pattern is a design pattern.

Template method: UML class diagram.

A template method defines the skeleton of an algorithm in terms of abstract operations which subclasses override to provide concrete behavior.

First a class is created that provides the basic steps of an algorithm by using abstract methods. Later on, subclasses change the abstract methods to implement real actions. Thus the general algorithm is saved in one place but the concrete steps may be changed by the subclasses.

Example in Java

/**
 * An abstract class that is common to several games in
 * which players play against the others, but only one is
 * playing at a given time.
 */

abstract class Game{

  private int playersCount;

  abstract void initializeGame();

  abstract void makePlay(int player);

  abstract boolean endOfGame();

  abstract void printWinner();

  /* A template method : */
  final void playOneGame(int playersCount){
    this.playersCount = playersCount;
    initializeGame();
    int j = 0;
    while( ! endOfGame() ){
      makePlay( j );
      j = (j + 1) % playersCount;
    }
    printWinner();
  }
}

Now we can extend this class in order to implement existing games:

class Monopoly extends Game{

  /* Implementation of necessary concrete methods */

  void initializeGame(){
    // ...
  }

  void makePlay(int player){
    // ...
  }

  boolean endOfGame(){
    // ...
  }

  void printWinner(){
    // ...
  }
 
  /* Specific declarations for the Monopoly game. */

  // ...

}
class Chess extends Game{

  /* Implementation of necessary concrete methods */

  void initializeGame(){
    // ...
  }

  void makePlay(int player){
    // ...
  }

  boolean endOfGame(){
    // ...
  }

  void printWinner(){
    // ...
  }
 
  /* Specific declarations for the Chess game. */

  // ...

}

Example in C++

C++ code below let's the client sort in ascending or descending order using BubbleSort. Deriving more classes from BubbleSort may cause the objects to lose communicating behavior. Use Strategy pattern to avoid this problem.

Output:

Archduke
Ceasar
Emperor
President
Prime Minister
Queen
Warlord

Warlord
Queen
Prime Minister
President
Emperor
Ceasar
Archduke
// Template Method.cpp : Defines the entry point for the console application.

#include <string> #include <cstddef> #include <iostream>
class BubbleSort { public:   BubbleSort(std::string* Array, const std::size_t size) : _Array(Array), _Size(size)    { } public:   virtual void Sort()   {     for(std::size_t i = _Size; i-- > 0; )     {       for(std::size_t j = 0 ; j < _Size-1; j++)       {         if( OutOfOrder(_Array[j], _Array[j+1]) )         {           Swap(j, j+1);         }       }     }   }
private:     void Swap(const unsigned a, const unsigned b)   {     std::string tmp = _Array[a];     _Array[a] = _Array[b];     _Array[b] = tmp;   }   virtual bool OutOfOrder(const std::string&, const std::string& )=0; private:     std::string* _Array;   const std::size_t _Size; };
//---------------------------------------------------------------------
class BubbleAscSort : public BubbleSort { public:   BubbleAscSort(std::string* Array, const std::size_t size) : BubbleSort(Array, size)   { } public:   bool OutOfOrder(const std::string& a, const std::string& b)   {     return a > b;   } };
//----------------------------------------------------------------------
class BubbleDescSort : public BubbleSort { public:   BubbleDescSort(std::string* Array, const std::size_t size) : BubbleSort(Array, size)   { } public:   bool OutOfOrder(const std::string& a, const std::string& b)   {     return a < b;   } };
//----------------------------------------------------------------------
int main() {   std::string sLeaderTypes[7]={ "President""Queen""Warlord""Ceasar",     "Prime Minister""Emperor""Archduke"};   const std::size_t size = sizeof sLeaderTypes / sizeof *sLeaderTypes;
  //Use BubbleSort and sort in ascending order.   BubbleAscSort bas(sLeaderTypes, size);   bas.Sort();   //Show the results.   for(std::size_t i = 0; i < size; ++i)   {     std::cout<<sLeaderTypes[i]<<std::endl;   }   std::cout<<std::endl;
  //Use BubbleSort and sort in descending order.   BubbleDescSort bdsc(sLeaderTypes, size);   bdsc.Sort();   //Show the results.   for(std::size_t i = 0; i < size; ++i)   {     std::cout<<sLeaderTypes[i]<<std::endl;   }   std::cout<<std::endl;

  return 0; }