Problem

When two (or more) components do not share common interface or implentation but do have significant functional similarities, duplicate effore will be expended to make one change to both.

Solution

Define the skeleton of an algorithm, allowing the most important parts to be filled in by client subclasses. The Template Method pattern lets subclasses tweak parts of an algorithm to suit its purpose without changing the algorithm itself.

Related Patterns

Discussion

The algorithm designer decides which parts of the algorithm are standard to all subclasses and which parts are variable (left to the subclasses to define). Variable parts can be given a default implementation or left purposely blank.

Examples

The Template pattern is used prominently in the design and implementation of frameworks. Placeholders are left in place for the user to fill in as needed. This pattern book uses the Template pattern extensively: common headers are templated and included where needed.

Code

This function generates the HTML markup (including the proper CSS classes) for a Bootstrap Dropdown Menu from an associative array of links. If the first level is a link, it is included directly in the markup. Otherwise, if an item contains an array (meant here as a submenu), menu items are added for each link in the submenu array. This helps reduce the need for messy HTML markup and also we can change the menu with one change to a menu array (when we are using a common header).

  function build_bootstrap_dropdown_menu($arr){
    $ret = "";
    foreach($arr as $name => $val){
      if(is_array($val)){
        $ret .= "<li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
          aria-haspopup="true" aria-expanded="false">$name<span class="caret"></span></a><ul class="dropdown-menu">";
        foreach($val as $name => $href) $ret .= "<li><a href=\"$href\">$name</a></li>";
        $ret .= "</ul></li>";
      }
      else{
        $ret .= "<li><a href=$val>$name</a></li>";
      }
    }
    return $ret;
  }