Design Pattern: Template Method Pattern in PHP

Template method pattern defines a template/skeleton for an operation processing steps. The subclasses define some steps of the template/skeleton, and some step definitions can be common for all.

This makes it easier for the subclasses to adopt the processing steps defined in the template method pattern.

This article demonstrates Template Method pattern implementations in PHP. Check the following implementation details and examples.

Implementation

Here is a simple example of the Template Method pattern in PHP-

  • Create abstract(template) class. Declare some abstract methods. Define the common methods in the class. Define a method for the main processing and call the methods as per requirement.
  • Define concrete classes as template implementation. Extend the abstract template class. Define the methods that are abstract in the template class.

Here is a simple implementation of Template Method in PHP-

<?php
// General Template Method Pattern implementation in PHP

// Abstract Template
abstract class Template {
    abstract function stepA(): void;
    abstract function stepB(): void;

    public function stepC(): void {
        echo "Executing Step C - common in Template\n";
    }

    private function stepD(): void {
        echo "Executing Step D  - common in Template\n";
    }

    public function process(): void {
        $this->stepA();
        $this->stepB();
        $this->stepC();
        $this->stepD();
    }
}

// Concrete Template implementation
class ConcreteA extends Template {
    public function stepA(): void {
        echo "Executing Step A of ConcreteA\n";
    }

    public function stepB(): void {
        echo "Executing Step B of ConcreteA\n";
    }
}

// Concrete Template implementation
class ConcreteB extends Template {
    public function stepA(): void {
        echo "Executing Step A of ConcreteB\n";
    }

    public function stepB(): void {
        echo "Executing Step B of ConcreteB\n";
    }
}

// Demo
// Use ConcreteA
$concreteA = new ConcreteA();
$concreteA->process();

// Use ConcreteB
$concreteB = new ConcreteB();
$concreteB->process();

Output will be as below-

Executing Step A of ConcreteA
Executing Step B of ConcreteA
Executing Step C - common in Template
Executing Step D  - common in Template


Executing Step A of ConcreteB
Executing Step B of ConcreteB
Executing Step C - common in Template
Executing Step D  - common in Template

Examples

Check the following examples of Template method pattern implementation in PHP-

Example #1: Transport Construction

In this example, we are discussing a system that constructs transports like – Bus, Plane, Train, etc.

Transport Abstract Class

  • Create file “Transport.php”.
  • Define abstract class “Transport”.
  • Declare abstract functions – “createBody”, “addEngine”, “addWheel”, “addWing”.
  • Define methods that are common for all the transports – “addSeat”, “paint”.
  • Finally, define the method “build”. This is the main processing method, it combines all the steps.
<?php
// Transport.php

namespace BigBoxCode\DesignPattern\TemplateMethod\Transport;

abstract class Transport {
    abstract function createBody(): void;
    abstract function addEngine(): void;
    abstract function addWheel(): void;
    abstract function addWing(): void;

    private function addSeat(): void {
        echo "Adding seats - Common process\n";
    }

    private function paint(): void {
        echo "Painting - Common process\n";
    }

    public function build(): void {
        $this->createBody();
        $this->addEngine();
        $this->addWheel();
        $this->addWing();
        $this->addSeat();
        $this->paint();
    }
}

Car Transport Class

  • Create file “Car.php”.
  • Create class “Car”, and extend “Transport” abstract class.
  • Define the abstract methods in this class – “createBody”, “addEngine”, “addWheel”, “addWing”(this is kept blank as wings are not applicable for cars).
<?php
// Car.php

namespace BigBoxCode\DesignPattern\TemplateMethod\Transport;


class Car extends Transport {
    public function createBody(): void {
        echo "Creating Car Body\n";
    }

    public function addEngine(): void {
        echo "Adding Engine to Car\n";
    }

    public function addWheel(): void {
        echo "Adding 4 Wheels to Car\n";
    }

    public function addWing(): void {
        // Not required for Car
    }
}

Bike Transport Class

  • Create file “Bike.php”.
  • Create class “Bike”, and extend “Transport” for this class. Define the abstract methods in this class.
<?php
// Bike.php

namespace BigBoxCode\DesignPattern\TemplateMethod\Transport;

class Bike extends Transport {
    public function createBody(): void {
        echo "Creating Bike Body\n";
    }

    public function addEngine(): void {
        echo "Adding Engine to Bike\n";
    }

    public function addWheel(): void {
        echo "Adding 2 Wheels to Bike\n";
    }

    public function addWing(): void {
        // not required for Bike
    }
}

Plane Transport Class

  • Create file “Plane.php”.
  • Create class “Plane”, extend “Transport” for this class, and define the abstract methods in this class.
<?php
// Plane.php

namespace BigBoxCode\DesignPattern\TemplateMethod\Transport;

class Plane extends Transport {
    public function createBody(): void {
        echo "Creating Plane Body\n";
    }

    public function addEngine(): void {
        echo "Adding Engine to Plane\n";
    }

    public function addWheel(): void {
        echo "Adding 3 Wheels to Plane\n";
    }

    public function addWing(): void {
        echo "Adding Wings Plane\n";
    }
}

Train Transport Class

  • Create file “Train.php”.
  • Create class “Train”, extend “Transport” for this class, and define the abstract methods in this class.
<?php
// Train.php

namespace BigBoxCode\DesignPattern\TemplateMethod\Transport;

class Train extends Transport {
    public function createBody(): void {
        echo "Creating Train Body\n";
    }

    public function addEngine(): void {
        echo "Adding Engine to Train\n";
    }

    public function addWheel(): void {
        echo "Adding Wheels to Train\n";
    }

    public function addWing(): void {
        // not required for train
    }
}

Demo

In the client, create object of the transport class. And call the “build” method for the final building of the transport.

<?php
// demo.php

require __DIR__ . '/../../vendor/autoload.php';

use BigBoxCode\DesignPattern\TemplateMethod\Transport\Car;
use BigBoxCode\DesignPattern\TemplateMethod\Transport\Plane;

// Build Car
$car = new Car();
$car->build();

// Build Plane
$plane = new Plane();
$plane->build();

Output

Following output will be generated-

Creating Car Body
Adding Engine to Car
Adding 4 Wheels to Car
Adding seats - Common process
Painting - Common process


Creating Plane Body
Adding Engine to Plane
Adding 3 Wheels to Plane
Adding Wings Plane
Adding seats - Common process
Painting - Common process

Example #2: Database Backup

Here we want to implement a database backup system. The common steps of the backup will be contained in the abstract template class, and the specific/specialized methods(like the dump process) will be in the specific class for each database.

Database Backup Class [Abstract Template]

  • Create file “DatabaseBackup.php”.
  • Define abstract class “DatabaseBackup”.
  • Declare abstract functions – “dump”(will be used for writing specific database dump process).
  • Define common methods – “initialCheck”, “validate”, “compress”, “version”, “save”.
  • Define method “process” for the final processing. This method combines all the steps. Make this method public so that the client can access and call this method.
<?php
// DatabaseBackup.php

namespace BigBoxCode\DesignPattern\TemplateMethod\DatabaseBackup;


abstract class DatabaseBackup {
    public function __construct(protected string $location) {

    }

    // For specific dump process for specif database
    abstract protected function dump(): void;

    private function initialCheck(): void {
        // Perform initial checking
        // Check the last stored version
        // and data of the last saved version

        echo "Perform initial check\n";
    }

    private function validate(): void {
        // Validate the database dump
        // Check if dump is done peroperly
        // and saved in the specified location

        echo "Validate database dump\n";
    }

    private function compress(): void {
        // Compress dump file before saving

        echo "Compress database dump file\n";
    }

    private function version(): void {
        // Set version of the dump file
        // Check the last version saved
        // and set the new version name

        echo "Set the version of the new dump\n";
    }

    private function save(): void {
        // Save database dump

        echo "Save database dump to specific location: {$this->location}\n";
    }

    public function process(): void {
        $this->initialCheck();
        $this->dump();
        $this->validate();
        $this->compress();
        $this->version();
        $this->save();
    }

}

MySQL Backup Class [Extends DatabaseBackup]

  • Create file “MysqlBackup.php”.
  • Extend the abstract class “DatabaseBackup”.
  • Define the method “dump” (as part of the DatabaseBackup extension). Write the steps specific for the MySQL database dump, and saving the dump file.
<?php
// MysqlBackup.php

namespace BigBoxCode\DesignPattern\TemplateMethod\DatabaseBackup;

class MysqlBackup extends DatabaseBackup {
    public function __construct(string $location) {
        parent::__construct($location);
    }

    protected function dump(): void {
        // Dump MySQL database
        // Write specific process
        // for specifically MySQL DB backup

        echo "Performing steps for MySQL database dump\n";
    }
}

Postgres Backup Class [Extends DatabaseBackup]

  • Create file “PostgresBackup.php”.
  • Define class “PostgresBackup”, extend “DatabaseBackup” for the class, and define the “dump” method with specific dump process for Postgres.
<?php
// PostgresBackup.php

namespace BigBoxCode\DesignPattern\TemplateMethod\DatabaseBackup;

class PostgresBackup extends DatabaseBackup {
    public function __construct(string $location) {
        parent::__construct($location);
    }

    protected function dump(): void {
        // Dump Postgres database
        // Write specific process
        // for specifically Postgres DB backup

        echo "Performing steps for Postgres database dump\n";
    }
}

SQL Server Backup Class [Extends DatabaseBackup]

  • Create file “SqlserverBackup.php”.
  • Define class “SqlserverBackup”, and extend “DatabaseBackup” for the class.
<?php
// SqlserverBackup.php

namespace BigBoxCode\DesignPattern\TemplateMethod\DatabaseBackup;

class SqlserverBackup extends DatabaseBackup {
    public function __construct(string $location) {
        parent::__construct($location);
    }

    protected function dump(): void {
        // Dump SQL Server database
        // Write specific process
        // for specifically SQL Server DB backup

        echo "Performing steps for SQL Server dump\n";
    }
}

MongoDB Backup Class [Extends DatabaseBackup]

  • Create file “MongodbBackup.php”.
  • Define class “MongodbBackup”, and extend the “DatabaseBackup”.
<?php
// MongodbBackup.php

namespace BigBoxCode\DesignPattern\TemplateMethod\DatabaseBackup;

class MongodbBackup extends DatabaseBackup {
    public function __construct(string $location) {
        parent::__construct($location);
    }

    protected function dump(): void {
        // Dump MongoDb database

        // Write specific process
        // for specifically MongoDB DB backup

        echo "Perform steps for MongoDB database dump\n";
    }
}

SQLite Backup Class [Extends DatabaseBackup]

  • Create file “SqliteBackup.php”.
  • Define “SqliteBackup” class, and extend “DatbaseBackup”.
<?php
// SqliteBackup.php

namespace BigBoxCode\DesignPattern\TemplateMethod\DatabaseBackup;

class SqliteBackup extends DatabaseBackup {
    public function __construct(string $location) {
        parent::__construct($location);
    }

    protected function dump(): void {
        // Dump SQLite database
        // Write specific process
        // for specifically SQLite DB backup

        echo "Performing steps for SQLite database dump\n";
    }
}

Demo

Create an object of the database backup class like “MysqlBackup”, or “MongodbBackup”, etc.

Then we can call the “process” function for processing the backup fully.

<?php
// demo.php

require __DIR__ . '/../../vendor/autoload.php';

use BigBoxCode\DesignPattern\TemplateMethod\DatabaseBackup\MongodbBackup;
use BigBoxCode\DesignPattern\TemplateMethod\DatabaseBackup\MysqlBackup;
use BigBoxCode\DesignPattern\TemplateMethod\DatabaseBackup\SqlserverBackup;


// MySQL Backup
$mysqlBackup = new MySQLBackup("/home/backup/mysql/");
$mysqlBackup->process();

// MongoDB Backup
$mongodbBackup = new MongodbBackup('/home/backup/mongo/');
$mongodbBackup->process();

// SQL Server backup
$sqlserverBackup = new SqlserverBackup("/home/backup/mssql/");
$sqlserverBackup->process();

Output

Output will be as below-

Perform initial check
Performing steps for MySQL database dump
Validate dabase dump
Compress database dump file
Set the version of the new dump
Save database dump to specific location: /home/backup/mysql/


Perform initial check
Perform steps for MongoDB database dump
Validate dabase dump
Compress database dump file
Set the version of the new dump
Save database dump to specific location: /home/backup/mongo/


Perform initial check
Performing steps for SQL Server dump
Validate dabase dump
Compress database dump file
Set the version of the new dump
Save database dump to specific location: /home/backup/mssql/

Source Code

Use the following link to get the source code:

Other Code Implementations

Use the following links to check Template Method pattern implementation in other programming languages.

Leave a Comment


The reCAPTCHA verification period has expired. Please reload the page.