Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / PHP

Design patterns Part I – Singleton

5.00/5 (1 vote)
16 Aug 2010CPOL2 min read 7K  
The first part of a set of explained design patterns
Procedural vs object- oriented

One core difference between object-oriented and procedural code can be found in the way that responsibility is distributed. Procedural code takes the form of a sequential series of commands and method calls. The controlling code tends to take responsibility for handling differing conditions. This top-down control can result in the development of duplications and dependencies across a project. Object-oriented code tries to minimize these dependencies by moving responsibility for handling tasks away from client code and toward the objects in the system.

While the procedural code busies itself about details, the object-oriented code works only with an interface, unconcerned about the details of implementation. Because responsibility for implementation lies with the objects and not with the client code, it would be easy to switch in support for new formats transparently.

How should we think about defining classes? The best approach is to think of a class as having a primary responsibility and to make that responsibility as singular and focused as possible. Put the responsibility into words. It has been said that you should be able to describe a class’s responsibility in 25 words or less, rarely using the words "and" or "or". If your sentence gets too long or mired in clauses, it is probably time to consider defining new classes along the lines of some of the responsibilities you have described.

Singleton:

The problem:

We need a single instance of an object. Think about a connection to a database. When we create a class that handles database connection we want the instance of that class to be unique all over the application. In procedural mode we would try to define a global variable (or a constant) and to use it. This is not an efficient way of doing things because we can forget to declare it in some files or we can encounter a server that has global variables turn off. In object oriented mode we would define a static method within a class that would give us only one instance of the same object.

The solution (implementation):

Example for procedural mode:

//index.php
define("CONN");
CONN = mysql_connect("server", "username", "password");
$dbSelected = mysql_select_db("database_name", CONN);
if($dbSelected){
    $result = mysql_query("SELECT * FROM `users`", CONN);
    //do something with the result got from database (display it, for example)
}

//functions.php
if(!defined(CONN)){
   define("CONN");
   CONN = mysql_connect("server", "username", "password");
   $dbSelected = mysql_select_db("database_name", CONN);
}
function test(){
    if($dbSelected){
        $result = mysql_query("SELECT * FROM `categories`", CONN);
        //display the result
    }
}


Example for object oriented mode:

class Connection{
    private static $instance;
    
    private function __construct(){
       self::$instance = mysql_connect("server", "username", "password");
       mysql_select_db("database_name", self::$instance);
    }
    
    //!!! This method checks to see if the instance already exists, if exists this will be used, else the instance is created
    public static function getInstance(){
        if(empty(self::$instance)){
            self::$instance = new Connection();
        }

        return self::$instance;
   }
}

//index.php
Connection::getInstance(); //here is created the connection
$result = mysql_query("SELECT * FROM `categories`");
//do something with the result got from database (display it, for example)

//functions.php
function test(){
    Connection::getInstance(); //because already exists, here the connection will be reused, NOT created again
    $result = mysql_query("SELECT * FROM `categories`");
    //display the result
}


OBS: You probably think that you could get the same behaviour throught a normal use of classes. Well, you are wrong, because in a normal use of classes you will have, probably, a public constructor that will be triggered every time you call the class. In this manner you will create several instances of database connection instead of only one.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)