Design Pattern: Template in PHP

Next in the Head First Design Patterns series is the Template Pattern. The template pattern defines the skeleton of an algorithm in a method and defers some of the implementation of the steps to the subclasses. The subclasses can redefine certain steps of the algorithm without changing the algorithm’s structure.

If you would like to tinker with the code, here’s a copy.

abstract class CaffeineBeverage{
    public function prepareRecipe(){
        $this->boilWater();
        $this->brew();
        $this->pourInCup();
        $this->addCondiments();
    }

    protected abstract function brew();

    protected abstract function addCondiments();

    protected function boilWater(){
        echo("Boiling Water");
        echo("<br />");
    }

    protected function pourInCup(){
        echo("Pouring into cup");
        echo("<br />");
    }
}
include_once('caffeineBeverage.php');

class Coffee extends CaffeineBeverage{
    public function brew(){
        echo("Dripping Coffee through filter");
        echo("<br />");
    }

    public function addCondiments(){
        echo("Adding Sugar and Milk");
        echo("<br />");
    }
}
include_once('caffeineBeverage.php');

class Tea extends CaffeineBeverage{
    public function brew(){
        echo("Steeping the tea");
        echo("<br />");
    }

    public function addCondiments(){
        echo("Adding Lemon");
        echo("<br />");
    }
}
abstract class CaffeineBeverageWithHook{
    public function prepareRecipe(){
        $this->boilWater();
        $this->brew();
        $this->pourInCup();
        if($this->customerWantsCondiments()){
            $this->addCondiments();
        }
    }

    protected abstract function brew();

    protected abstract function addCondiments();

    protected function boilWater(){
        echo("Boiling Water");
        echo("<br />");
    }

    protected function pourInCup(){
        echo("Pouring into cup");
        echo("<br />");
    }

    protected function customerWantsCondiments(){
        return true;
    }
}
include_once('caffeineBeverageWithHook.php');

class CoffeeWithHook extends CaffeineBeverageWithHook{
    public function brew(){
        echo("Dripping Coffee through filter");
        echo("<br />");
    }

    public function addCondiments(){
        echo("Adding Sugar and Milk");
        echo("<br />");
    }

    public function customerWantsCondiments() {
        //need to implement way to read user's input
        return false;
    }

}
include_once('caffeineBeverageWithHook.php');

class TeaWithHook extends CaffeineBeverageWithHook{
    public function brew(){
        echo("Steeping the tea");
        echo("<br />");
    }

    public function addCondiments(){
        echo("Adding Lemon");
        echo("<br />");
    }

    public function customerWantsCondiments() {
        //need to implement way to read user's input
        return false;
    }
}
include_once('tea.php');
include_once('coffee.php');
include_once('coffeeWithHook.php');
include_once('teaWithHook.php');

class BeverageTestDrive {

    public static function main() {
        $tea = new Tea();
        $coffee = new Coffee();

        echo("Making tea...");
        echo("<br />");
        $tea->prepareRecipe();
        echo("<br />");

        echo("Making coffee...");
        echo("<br />");
        $coffee->prepareRecipe();
        echo("<br />");

        echo("Making tea with hook...");
        echo("<br />");
        $teaHook = new TeaWithHook();
        $teaHook->prepareRecipe();
        echo("<br />");

        echo("Making coffee with hook...");
        echo("<br />");
        $coffeeHook = new CoffeeWithHook();
        $coffeeHook->prepareRecipe();
    }

}

BeverageTestDrive::main();

Leave a Reply




You may use the tags listed below in your comments:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>