How and when to use the singleton design pattern
Published | 03. Nov 2010, 18:02 |
Pages
|
Here I'll show you how to implement the singleton design pattern in PHP and C#. I also give pointers of when it's appropriate to implement the pattern.
The purpose of the singleton pattern shines through in its name. We use it when we want to restrict the number of object instances of a class to one single instance. There might be numerous reasons for introducing such of a restriction. It might be for performance and memory reasons, retaining state information or to make sure your dealing with only one particular instance across the system.
Some popular uses of the singleton pattern is the database connection class, configuration classes where you'd want to retain the settings for later and factory classes which are instantiated several times in the system. Note that these examples are not limited to the singleton pattern, you should only implement this pattern if it's appropriate for your case.
Now I'll show you an implemention of the singleton pattern. Notice that instantiation of the class
is constricted to a single method, here: getInstance()
. The class instance is stored
in the private scoped variable $instance
. Both of these members are static so they
are easily accessible in the global scope (expect for the instance property of course).
class MySingleton { // property that holds the instance static private $instance; // method that instantiates class and restricts number of instances static function getInstance() { if (!(self::$instance instanceof self)) { self::$instance = new self(); } return self::$instance; } // prevent cloning and normal instantiation private function __construct() {} private function __clone() {} }
The example can be used like this:
// works $instance = MySingleton::getInstance(); // fails $instance = new MySingleton(); // fails $secondInstance = clone $instance;
As you can see from the previous example, the MySingleton
class is solely
responsible for making sure only one instance of itself is created. This is much safer than
for example storing the instance in a global variable.
Now I'll show you a more practical example using a database connection class. First I show you how you could do it without using singleton and then I show the you the same example using the singleton pattern.
// Using global variable function getUsers() { global $db; $res = $db->query('select * from users'); // ... } // Using constructor function getUsers() { $db = new DBConnection(); $res = $db->query('select * from users'); // ... } // Using singleton function getUsers() { $db = DBConnection::getInstance(); $res = $db->query('select * from users'); // ... }
As you can see the two first examples have obvious flaws. The first example uses global variables, this is a big no-no. You should always try to avoid using them as they pollute the global scope, are prone to override errors and are hard to keep track of and maintain. In the second example we are using a constructor to instantiate the class. The downside of this solution becomes more clear when we want the changes made in the instance to be reflected in the later instantiations of the class. Of course you could be using static variables for this purpose, but why not just keep it simple and make sure only one instance is used? Also if the construction of the object is expensive then using the singleton pattern will be a mighty relief.
That concludes this brief introduction to the singleton design pattern. You should now be ready to implement this in your own projects.