Posts tagged as:

design pattern

The Singleton design pattern creates a class that can only have one instance. This is useful for tasks such as creating a globally available database connection for your script.

The prototype for the singleton class, in PHP, goes like this:

Singleton Pattern

class ClassName {     static $instance = NULL;     private function __construct() {}     private function __clone() {}     static function getInstance() {         if(self::$instance === NULL) self::$instance = new ClassName();         return self::$instance;     }

     $obj = ClassName::getInstance();}

In PHP, variables have scope restrictions that prevent them from being visible in all parts of your program. We often need these variables inside classes and functions, for example. One way to provide globally accessible variables is to pass them into classes or functions as parameters. This method makes it clear that the function of class method is dependent on an external variable or object. Here’s an example:

Option #1: Pass the Variable As A Parameter

Here’s an example of passing a database handle into a hypothetical function and into a class.

function logger($info, $dbhandle);

class Logger {    static $handle = NULL;    static function logIt($info, $dbhandle) {         self::$handle = $dbhandle;    }}

When you have only a few parameters this tactic works fine, but if your functions have many parameters the result is unwieldly code. It is not uncommon to find programmers creating functions or methods that have parameteritis, with dozens of confusing parameters.

Fortunately, a singleton class provides a cleaner solution: it provides global availability of a single object—with the side-effect that the sole object cannot be modified. If we want to ensure that this class cannot be cloned or sub-classed, we will mark it as final and the construct() and clone() methods as protected.

Option #2: Use a Singleton Class

Here’s an example a properly formed singleton class that cannot be cloned or sub-classed, ensuring that there will only be one instance of this class.

final class DbConnection {

    private static $handle = null;    private static $instance = NULL;    private static $db = 'default.db';

    // Deny new DbConnection();    private function __construct($db = NULL) {} 

    // We deny cloning, as with:     //     $instance = DbConnection::connect();    //     $clone = $instance;    private function __clone() {} 

    function connect() {        if(is_null(self::$handle)) {            if(defined('DEFAULT_DB') {                self::$db = DEFAULT_DB;            }            // Create the only possible instance of this class            self::$handle = new SqliteDatabase(self::$db);        }        return self::$handle;    }

    static function getInstance() {        if(self::$instance === NULL) {            self::$instance = new DbConnection();        }        return self::$instance;    }}

This class encapsulates the entire process of creating the single instance and the database handle, and checks to see if a default database constant exists. We can use it this way:

class Logger {    // Notice that this, too, is a singleton pattern class.    static private $logger = NULL;

    static function logIt($it) {        $dbc = DbConnection::getInstance()->connect();        if(self::$instance == NULL) {             self::$instance = new Logger);        }    }

    private function __construct() {}

}

Refactoring

Since the sole function of the DbConnection class is to provide a database connection, we can simplify the code considerably by eliminating the getInstance() method:

final class DbConnection {

    private static $handle = null;    private static $db = 'default.db';

    // Deny new DbConnection();    private function __construct($db = NULL) {} 

    // We deny cloning    private function __clone() {} 

    function connect() {        if(is_null(self::$handle)) {            if(defined('DEFAULT_DB') {                self::$db = DEFAULT_DB;            }            // Create the only possible instance of this class            self::$handle = new SqliteDatabase(self::$db);        }        return self::$handle;    }    

}

class Logger {

    static private $logger = NULL;

    static function logIt($it) {        $dbc = DbConnection::connect();        if(self::$instance == NULL) {             self::$instance = new Logger);        }    }

    private function __construct() {}

}

Happy hacking…

2 comments

The Registry design pattern gives us a way to overcome scoping complexities in your object-oriented programs. In this post I want to talk about how we use a Registry class in the MojoMVC.

PHP Scope: Main, Class, and Method

Though my diagram looks like the interior of a single-celled animal, I mean to suggest that the attributes inside classes are encapsulated within impermeable walls. And that classes are impermeable to the global variables in Main. This is a good thing in OOP Land.

In the MojoMVC, every request requires a Request object. There are times when other objects need that information. PHP has global variables by default, with local variables inside regular functions, and public, protected, and private methods inside classes. Since we don’t speak Kludge here, we need a another strategy for passing information around. The Registry pattern fills the bill.

We use the Registry class to take advantge the fact that classes have super global visibility—they can walk through walls like the super global variables ($_GET, $_POST, etc), functions, and constants. In other words, our Registry class can function as a super global delivery messenger as long as we give it some static setters and getters.

The Registry Class

1    class Registry extends Base {
2       static private $data = array();
3
4       private function __construct() {}
5
6       static public function get($key)
7       {
8          return self::$data[$key];
9       }
10
11       static public function set($key,$value)
12       {
13          self::$data[$key] = $value;
14       }
15    }

We can use it like this:

Registry::set(‘string’, ‘this is the name’);
print Registry::get(‘string’);  // output: this is the name

class NextClass {
function __construct() {
print Registry::get(‘string’);
}
}


$n = new NextClass;  // output: this is the name

Now we have a class that walks through walls to deliver the values stored inside it. All we have to do is store the Request object in the Registry, like this:

Registry::set(‘request’, $this->r);

You’re probably wondering where $this->r came from. That’s an interesting story, but it will have to wait until next time.

For more information on the Registry pattern, check out your friendly Google.

0 comments