Use the Template Method Design Pattern | PHP Code Examples in 2023

CraftyTechie is reader-supported. When you buy through links on our site, we may earn an affiliate commission.

Using the Template Method Pattern in PHP

The template method pattern is a behavioral design pattern that defines the steps of an algorithm and allows sub-classes to provide an implementation for one or more steps without affecting the algorithm structure.

Article Highlights

  • The template method defines the steps or skeleton of an algorithm and allows sub-classes to override one or more of these steps.
  • Benefit – Helps remove code duplication, making the system less rigid to changes.
  • Con – May limit flexibility in tinkering with the steps of an algorithm.

Template Design Pattern PHP Code Example

<?php


abstract class IceTea {


   public function prepareIceTea() {


       $this->addBoilWater();
       $this->addTeaBag();
       $this->addSugar();
       $this->brewTea();
       $this->addColdWater();
       $this->addIce();
   }


   public function addBoilWater() {
       echo "Adding boil water"."\n";
   }


   public abstract function addTeaBag();


   public function addSugar() {
       echo "Adding sugar"."\n";
   }


   public function brewTea() {
       echo "Brewing tea"."\n";
   }


   public function addColdWater() {
       echo "Adding cold water"."\n";
   }


   public function addIce() {
       echo "Adding ice"."\n";
   }
}


class PeachTea extends IceTea {


   public function addTeaBag() {
       echo "Adding peach tea bag"."\n";
   }
}


class PineappleTea extends IceTea {




   public function addTeaBag() {
       echo "Adding pineapple tea bag"."\n";
   }
}


function main() {


   $peachTea = new PeachTea();
   $pineappleTea = new PineappleTea();


   echo "Making peach ice tea"."\n";
   $peachTea->prepareIceTea();


   echo "\n"."Making pineapple ice tea"."\n";
   $pineappleTea->prepareIceTea();
}


/*
Making peach ice tea
Adding boil water
Adding peach tea bag
Adding sugar
Brewing tea
Adding cold water
Adding ice


Making pineapple ice tea
Adding boil water
Adding pineapple tea bag
Adding sugar
Brewing tea
Adding cold water
Adding ice
*/
?>
template method pattern php

What is the Template Method Pattern

“The template method pattern is a behavioral design pattern that defines the steps of an algorithms and allows sub-classes to provide implementation for one or more steps without affecting the algorithm structure.”

template method pattern php

Template Method Pattern Example

CubeTea is a new venture in town serving ice teas via ice tea machines. Customers can choose flavour, pay and have their chilled tea. Currently, they have tea bags for two flavours – Peach & Pineapple

recipe-steps

Developers were assigned a task to write code for automatic tea-making functionality. So, they come with two classes – PeachTea & PineappleTea.

<?php


class PeachTea {


   public function prepareIceTea() {     
       $this->addBoilWater();
       $this->addTeaBag();
       $this->addSugar();
       $this->brewTea();
       $this->addColdWater();
       $this->addIce();


   }


   public function addBoilWater() {
       echo "Adding boil water";
   }


   public function addPeachTeaBag() {
       echo "Adding peach tea bag";
   }


   public function addSugar() {
       echo "Adding sugar";
   }


   public function brewTea() {
       echo "Brewing tea";
   }


   public function addColdWater() {
       echo "Adding cold water";
   }


   public function addIce() {
       echo "Adding ice";
   }
}
?>
<?php


class PineappleTea {


   public function prepareIceTea() {
       $this->addBoilWater();
       $this->addTeaBag();
       $this->addSugar();
       $this->brewTea();
       $this->addColdWater();
       $this->addIce();


   }


   public function addBoilWater() {
       echo "Adding boil water";
   }


   public function addPineappleTeaBag() {
       echo "Adding pineapple tea bag";
   }


   public function addSugar() {
       echo "Adding sugar";
   }


   public function brewTea() {
       echo "Brewing tea";
   }


   public function addColdWater() {
       echo "Adding cold water";
   }


   public function addIce() {
       echo "Adding ice";
   }
}
?>

Problem 🙁

Code duplication

There is duplication across the common steps of the recipe. At the moment we have two of these classes but adding more classes in the future will increase duplication even further. Code duplication is a huge setback later when change requests and scheduled maintenance kick in.

Only one change to the common part of the code will lead you to modify all of these classes which opens up ways for bugs to crawl into the code. 

Lack of Abstraction

Software design principles rest on the idea of abstractions. In a more general sense, flexible software is always the one where high-level modules communicate without directly exposing concrete implementations. We have principles which state the significance of abstraction including the famous, “Program to abstractions not implementations”.

This problem can easily be tackled by introducing a new abstract class with all the common functions in one place and defining abstract functions for more specialized algorithms.

But won’t that couple the high-level module with the low-level module because the former will depend on the latter for these specialized functions? We will take inspiration from the dependency inversion principle which states that “A higher level module should depend on abstractions than implementation”.

dependency-inversion

Let’s see how we can go about this problem so that we can define a high-level module which is not coupled to concrete implementations.

Solution 🙂

As we have talked about an abstract class let’s bring it to life here. The idea is to define an abstract class which provides all the common function and make the exclusive functions abstract so that the sub-classes is bound to implement them.


Not sure about what is an abstract class? Learn more about abstract class in PHP.

<?php


abstract class IceTea {


   public function prepareIceTea() {
       $this->addBoilWater();
       $this->addTeaBag();
       $this->addSugar();
       $this->brewTea();
       $this->addColdWater();
       $this->addIce();


   }


   public function addBoilWater() {
       echo "Adding boil water";
   }


   public abstract function addTeaBag();


   public function addSugar() {
       echo "Adding sugar";
   }


   public function brewTea() {
       echo "Brewing tea";
   }


   public function addColdWater() {
       echo "Adding cold water";
   }


   public function addIce() {
       echo "Adding ice";
   }
}
?>

We want to summon your attention to the addTeaBag() abstract function. Since all the other functions are common so we keep them as is but a tea bag varies for different flavours so we will let the concrete PeachTea and PineappleTea.

These concrete classes will override the addTeaBag() to add their implementation.

<?php
class PeachTea extends IceTea {


   public function addTeaBag() {
       echo "Adding peach tea bag";
   }
}
?>
<?php
class PineappleTea extends IceTea {


   public function addTeaBag() {
       echo "Adding pineapple tea bag";
   }
}
?>

Defining a template method

So, the abstract class IceTea defines a template method prepareIceTea(). The method calls within these functions are steps of the recipe. Some steps are defined by the abstract class but the one which depends on the type of tea bag is left abstract.

template method pattern php

That’s wonderful because we removed the duplicate code and define a hierarchy with a high-level IceTea class. But how about coupling? Isn’t the abstract class dependent on the low-level or concrete classes for one of the steps of the recipe?

The Hollywood principle

The Hollywood principle states, “Don’t call us, we’ll call you” is closely related to the dependency control principles and defines a technique where a higher-level module decides when to call the low-level modules.

The low-level modules define some implementation or the missing piece of the puzzle and just hook into the system. The higher-level module defines the when and how of calling these low-level modules.

The client code ends up using just the higher-level modules without depending on the low-level modules. Let’s see how this applies to our system.

So, that’s pretty much the template method. Let’s see it in action.

Time to make some Ice Teas

Let’s test-drive the template method and make ourselves some ice tea.

<?php
function main() {


   $peachTea = new PeachTea();
   $pineappleTea = new PineappleTea();


   echo "Making peach ice tea"."\n";
   $peachTea->prepareIceTea();


   echo "\n"."Making pineapple ice tea"."\n";
   $pineappleTea->prepareIceTea();
}


/*
Making peach ice tea
Adding boil water
Adding peach tea bag
Adding sugar
Brewing tea
Adding cold water
Adding ice


Making pineapple ice tea
Adding boil water
Adding pineapple tea bag
Adding sugar
Brewing tea
Adding cold water
Adding ice
*/


?>

Using Hooks in the Template Method

The hooks are an add-on to the template method pattern and could help add some customization to the algorithm by doing something before or after an operation.

hooks

For instance, some customers may not want to add sugar to their tea. Now we don’t have any way in our current implementation to skip this step. So, what we can do instead is to define a hook.

Let’s add this hook function customerWantsSugar() to the abstract class. The abstract class will provide a default implementation (sugar will be added by default).

abstract class IceTea {


   public function prepareIceTea() {


       $this->addBoilWater();
       $this->addTeaBag();
       //Pre-hook
       if($this->customerWantsSugar()) {
           $this->addSugar();
       }
       $this->brewTea();
       $this->addColdWater();
       $this->addIce();
   }


   public function addBoilWater() {
       echo "Adding boil water"."\n";
   }


   public abstract function addTeaBag();


   public function addSugar() {
       echo "Adding sugar"."\n";
   }


   public function brewTea() {
       echo "Brewing tea"."\n";
   }


   public function addColdWater() {
       echo "Adding cold water"."\n";
   }


   public function addIce() {
       echo "Adding ice"."\n";
   }


   //Hook function
   public function customerWantsSugar() {
       return true;
   }
}
?>

Concrete classes can override this function and could define some other logic. For instance, accepting user input, as the examples show.

<?php
class PeachTea extends IceTea {


   public function addTeaBag() {
       echo "Adding peach tea bag"."\n";
   }


   public function customerWantsSugar() {
       echo "What do you want to input? y for yes n for no"."\n";


       //Ask for user input
       $input = trim(fgets(STDIN));


       if(trim(strtolower($input)) == "y") return true;


       elseif(trim(strtolower($input)) == "n") return false;


      
   }
}
?>

Benefits of the Template Method Pattern

  • Define common steps of an algorithm in one module or class.
  • Opens up a system for extension with new sub-classes providing unique implementations for specialized steps in an algorithm.
  • Helps remove code duplication, making the system less rigid to changes.

Complete Architecture | Template Method Pattern in PHP

template method pattern php

Template Method Pattern PHP Pseudocode Example

<?php


abstract class IceTea {


   public function prepareIceTea() {


       $this->addBoilWater();
       $this->addTeaBag();
       $this->addSugar();
       $this->brewTea();
       $this->addColdWater();
       $this->addIce();
   }


   public function addBoilWater() {
       echo "Adding boil water"."\n";
   }


   public abstract function addTeaBag();


   public function addSugar() {
       echo "Adding sugar"."\n";
   }


   public function brewTea() {
       echo "Brewing tea"."\n";
   }


   public function addColdWater() {
       echo "Adding cold water"."\n";
   }


   public function addIce() {
       echo "Adding ice"."\n";
   }
}


class PeachTea extends IceTea {


   public function addTeaBag() {
       echo "Adding peach tea bag"."\n";
   }
}


class PineappleTea extends IceTea {




   public function addTeaBag() {
       echo "Adding pineapple tea bag"."\n";
   }
}


function main() {


   $peachTea = new PeachTea();
   $pineappleTea = new PineappleTea();


   echo "Making peach ice tea"."\n";
   $peachTea->prepareIceTea();


   echo "\n"."Making pineapple ice tea"."\n";
   $pineappleTea->prepareIceTea();
}


/*
Making peach ice tea
Adding boil water
Adding peach tea bag
Adding sugar
Brewing tea
Adding cold water
Adding ice


Making pineapple ice tea
Adding boil water
Adding pineapple tea bag
Adding sugar
Brewing tea
Adding cold water
Adding ice
*/


?>

Pros and Cons of the Template Method Pattern in PHP

ProsCons
Removes code duplication and maximizes reuse of the existing code.The template method bloats up when the number of methods increases.
Confines most of the changes to one place in the software.May limit flexibility in tinkering with the steps of an algorithm.
Less hassle in adding new sub-classes classes.
The abstract class controls most of the algorithm and relies on the sub-classes for specific methods only. 

Where is the Template Method Pattern Used

Use the template method pattern when you want to

  • Implement a standardized process where most of the steps are identical except for a few.
  • Introduce sub-classes where each of them provides unique implementations for more specialized pieces of the algorithm.
  • Minimize code duplication in classes with identical methods.

What is the template method pattern

The template method pattern is a behavioural design pattern that defines the steps of algorithms and allows sub-classes to provide an implementation for one or more steps without affecting the algorithm structure.

The template method defers some implementation to the sub-classes so that they can be hooked up for providing specific implementation logic.

What is the dependency inversion principle

Dependency inversion principles state that “High level modules should not depend on low-level modules rather they both should depend on abstractions”

When modules depend on abstraction, they promote loosely coupled structures. Loosely coupled structures mean more flexible software where a change to a low-level module doesn’t propagate to other parts of the system.

What are the benefits of dependency inversion?

  • Produces loosely coupled and flexible software systems.
  • Testing and mocking become much easier.
  • Promotes reuse of most of the components across similar applications.

Using the Template Method Pattern in PHP Today

Phew! That’s all about the template method in PHP. Let’s review what we have seen thus far. The template method pattern is a behavioural design pattern that defines the steps of an algorithm and allows sub-classes to provide an implementation for one or more steps without affecting the algorithm structure.

The article features CubeTea, a new venture in town serving ice teas via automatic brewing machines. The machine runs on software and there is a module for making ice teas. The initial module uses two classes with almost identical codes for the common steps of recipes. Consequently, there is a lot of duplication across these classes.

Developers introduce an abstract class to reduce duplicate code and design a more flexible system. The abstract class includes functions for common steps of the recipe and defers more specialized steps to the sub-classes. The abstract class has a method that calls these steps: the template method.

The sub-classes extend the base class and override the abstract method, providing an implementation for the abstract function. 

Finally, the client code relies on the abstract class and the abstract class manages the logical flow of the algorithm and calls the right functions for every step.

That’s all. See you in another design pattern article.

Books on Design Patterns

Want to learn more about Design Patterns? There are many great resources online. We recommend the following books for your collection as they both can teach you the theoretical and the application of using design patterns in your day-to-day programming. Feel free to use the following Amazon affiliate links if you’d like to purchase them and a way to support our efforts.

Design Patterns: Elements of Reusable Object-Oriented Software

Design Patterns: Elements of Reusable Object-Oriented Software book

This is the book that started it all. I believe that every programmer should have a referenced copy to this book at some point in their career. There have been many updates and excellent newer content through the years, but this is a classic. It still stands the test of time and is just as relevant for today as it was in the original printing in the 90s.

Check it out on amazon

Learning PHP Design Patterns

This is an excellent book to go beyond the theory and apply it to writing good PHP code. Learning PHP Design Patterns is published by the popular O’Reilly media company. O’Reilly consistently publishes some of the most useful reference material related to software development. They are known to provide materials that thoroughly cover a topic in a way that is simple to understand. I recommend this book to every PHP developer.

Check it out on amazon

Want to see our full review of books on design patterns? Read our huge review article on over 15 design pattern books.

Design Patterns in PHP Learning Series.

This article is part of our series of design patterns in PHP. We are going through all of the patterns and showing how they can help you build better applications. Browse through our full list of patterns below.