QRdvark.com

Design Patterns

Design Patterns

by Kevin Waterson

Contents

  1. Abstract
  2. What is a Design Pattern
  3. Singleton
  4. Factory
  5. MVC
  6. Observer

Abstract

Design Patterns were first introduced to the world by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides. Collectively these became know as the "Gang of Four". These programmers found that within their code, certain patterns kept appearring. These patterns were of the type that formed a Framework for building their code upon.

This tutorial looks at 10 common design patterns and shows how they can be used.

What is a Design Pattern

A Design Pattern is a template, structure or framework on which you can build your application code. When the term Framework is used with regard to PHP, most folks immediately think MVC, and indeed, MVC is just one of many design patterns that will be covered here.

Singleton

The single pattern is an often used pattern in many applications when only a single instance of a resource is required. The most obvious type of resource for PHP web pages is a database connection, although other resource types can be used. When fetching of dynamically creating a web page several database calls may need to be made. If a single instance of the resource could be used, rather than creating several connections, the overhead is minimized. The single instance in this case, is created by the singleton pattern.


<?php

class db{

/*** Declare instance ***/
private static $instance NULL;

/**
*
* the constructor is set to private so
* so nobody can create a new instance using new
*
*/
private function __construct() {
  
/*** maybe set the db name here later ***/
}

/**
*
* Return DB instance or create intitial connection
*
* @return object (PDO)
*
* @access public
*
*/
public static function getInstance() {

if (!
self::$instance)
    {
    
self::$instance = new PDO("mysql:host='localhost';dbname='animals'"'username''password');;
    
self::$instance-> setAttribute(PDO::ATTR_ERRMODEPDO::ERRMODE_EXCEPTION);
    }
return 
self::$instance;
}

/**
*
* Like the constructor, we make __clone private
* so nobody can clone the instance
*
*/
private function __clone(){
}

/*** end of class ***/

?>

Lets look at what has happened in the singleton class above. A variable name $instance is created and made private, this ensures nobody and try to access it directly. Similarly, the constructor and __clone methods have been made private to prevent cloning of the class, or of somebody trying to instantiate an instance of it. The class has a single method for providing a resource, the getInstance() method.

The getInstance method checks that an instance does not already exist. If no instance exists a new instance of the PDO class is created and assigned to the $instance variable. If an existing instance is available, the getInstance() method returns this. The result is that the returned value is always the same instance, and no new resource, or overhead, is required.

Here is a small demonstration of how this might be used in an application.


<?php
try    {
    
/*** query the database ***/
    
$result DB::getInstance()->query("SELECT animal_type, animal_name FROM animals");

    
/*** loop over the results ***/
    
foreach($result as $row)
        {
        print 
$row['animal_type'] .' - '$row['animal_name'] . '<br />';
        }
    }
catch(
PDOException $e)
    {
    echo 
$e->getMessage();
    }
?>

Factory

The factory pattern is a class that creates objects for you, rather than you needing to use the new keyword to create one yourself. The factory is, as the name suggests, a factory for creating objects. Why do we need this? Lets consider an application that uses an ini file for configuration option. Then the application is changed to gain the configuration options from a database. The rest of the application falls apart like a house of cards as the base is removed.

This "tight coupling" of objects, where each object relies heavily on another, creates problems in larger applications. A system is needed where objects can reference each other, but are not inter dependent.

In our example of the configuration file becoming a database, if other classes were dependant on the classs that read from the ini file, and this was suddenly tasked to the database class problems occur.

By using the factory design pattern, if you change the type of object from the ini reader class to the database class you only need to change the factory. Any other code that uses the factory will be updated automatically.

<?php

/**
 *
 * @config interface
 */
interface Config
{
  function 
getName();
}


/**
 *
 * @config class
 *
 */
class userConfig implements Config{

/*
 * @username
 */
 
public $user_id;
 
/*** contructor is empty ***/
 
public function __construct$id ){
    
$this->user_id $id;
 }

 public static function 
Load$id ) {
    return new 
userConfig$id );
 }

 public function 
getName(){

    try
    {
        
/*** query the database ***/
        
$sql "SELECT username FROM user_table WHERE user_id=:user_id";
        
$db db::getInstance();
        
$stmt $db->prepare($sql)
        
$stmt->bindParam(':user_id'$this->user_idPDO::PARAM_INT);
        return 
$stmt->fetch(PDO::FETCH_COLUMN);    
    }
    catch(
PDOException $e)
    {
        
/*** handle exception here ***/
        
return false;
    }
 }

/*** end of class ***/

/*** returns instance of config ***/
$conf userConfig::Load);
echo 
$conf->getName();

?>

This might seem a little excessive code for simply retrieving a username. But in large scale application where a change from file based to database retrieval is made, the results could be catastrophic. Here its is simply a matter of changing the the getName() method retrieves the name, and the returned object is the same, thus allowing other parts of the application that require the username, eg: a login for a cart, to continue as they did previously.

MVC

Model View Controller

This is another quite common design pattern used in PHP. Many people are using Frameworks that implement MVC or an MVC variations. The topic is so vast it has gained a place of its own here at QRdvark at https://QRdvark.com/tutorials/Model-View-Controller-MVC.html, however, the topic will be covered briefly here.

The MVC design pattern is based on the principle of seperating business logic (Model) and presentation logic (View). The idea that changes to the view, or presentation layer, should not interfere with the Model. Also, that changes to the Model, or changes to the data, should not interfere with the presentation (View).

By introducing a third party intermediatory object (Controller), the Model and View can be independent of each other. The Controller handles input from the user interface (View) and passes this information to the Model. If the Model needs to respond, the Controller takes this reponse and supplies it to the View.

This seperation of business logic and presentation logic gives application developers wider flexibilty and promotes code reuse.

Observer

The observer design pattern is much like the factory pattern, as it provides a method of loosening the "tight coupling" between object. The observer pattern consists of two objects. One object makes itself observable, and another object observes it.

The eZ Components library's SignalSlot component uses the observer design pattern to "emit" a signal when an event occurs. The "signal" is then observed and an action taken.

This is how it works. A new cart item is object is instantiated and the CartItemLogger class instance is added as an observer and waits for a event. The instance is added to the cart_observers array.

When the addItem() method is run, the cart_observers array is traversed and the an instance with the onChanged method is run, using the name of the item as its second arguement. This provides the 'signal' for the running of the CartItemLogger->onChanged() method which contains the code required to log the event.


<?php
interface myObserver{
    function 
onChanged$sender$args );
}


interface 
myObservable{
    function 
addObserver$observer );
}


class 
CartItem implements myObservable{

 
/*
  * @observer array
  */
 
private $cart_observers = array();

 public function 
addItem$name ){
    foreach( 
$this->cart_observers as $obs )
    {
        
$obs->onChanged$this$name );
    }
 }

 
/*** add observer to observer array ***/
 
public function addObserver$observer ){
    
$this->cart_observers []= $observer;
 }

/*** end of class ***/


class CartItemLogger implements myObserver {

 public function 
onChanged$sender$args ){
    
/*** code to log item ***/
    
echo( "Logging: $args added to cart log" );
 }

/*** end of class ***/

$cart = new CartItem();
/*** when the observer is added, it listens for a signal ***/
$cart->addObserver( new CartItemLogger() );
$cart->addItem"book" );
?>

The strength of the observer pattern is that the itemList doesn't know what the logger is going to do. There could be other observers added that do other tasks when an item is added, eg: email the user that a copy of the order, or display an error if the item is not available.