| Object Oriented Design The Singleton Posted by: John in Programming, PHP, Object Oriented Programming, Design Patterns on Jul 16, 2008 |
One of the many annoyances of programming is a variables scope. Generally variables can be declared within the global namespace or the local namespace. When working with methods and classes global variables appear to be a good idea, however overuse of the global namespace can cause variables to clash, it also undermines encapsulation. Moreover, a class which depends on a global variable is coupled with the project rendering it impossible to reuse (unless the global variable is declared). This will lead to unwanted debugging. Using the singleton design pattern, you can make a class seemingly “global.” Although the code in this article is PHP, the concepts apply across almost every programming language.
Problem:
While designing my framework I found access to the database object was required by many classes. Since I only intend on connecting to a single database server, only one object of my database class would ever need to be instantiated. A novice programmer would create a database class which would look like the following:
To access any one of the methods you must instantiate the class then call the method:

Obviously the code above (assuming the methods have been implemented)will query the database. In most instances the code above is an acceptable practice. However, this will lead you down one of three roads: you will declare $db in the global namespace, you will instantiate a new database object each time it is needed, or you will end up passing $db to object X so when it creates object Y the database object can be passed. Alas, the learned programmer will choose to use the Singleton design pattern.
Solution:
The solution is to create a class that can only be instantiated itself. Moreover, it should not instantiate more than once instance of itself. We start by making the constructor private, creating a new static method which I will call getInstance(), and a new static variable which I will call $instance.
Since the constructor is private, to convey the configuration settings to the database call we will need to pass them to the getInstance() function. Here is where the magic happens. The static variable $instance is used to hold the instance of this class (if one exists). Since we only want one instance to ever be created, we will check to see if $instance has already been set, if it has not, we will set $instance to a new instance of the object then return it. If it has been set, we will simply return the already created object. Confused? Take a look at the code " it should clear things up:
To use this class, we use PHP's scope resolution operator, which allows us to access a static function of a class, without instantiating it.
We can now call the database::getInstance($config_info) from any class as many times as we want, without creating a new object. Moreover, we can access the same exact object created in a different location of our application essentially providing “global” access.
Problem:
While designing my framework I found access to the database object was required by many classes. Since I only intend on connecting to a single database server, only one object of my database class would ever need to be instantiated. A novice programmer would create a database class which would look like the following:

- class database {
- private $host;
- private $username;
- private $password;
- private $database;
- public function __construct(array $config) {
- $this->host = $config['host'];
- $this->username = $config['username'];
- $this->password = $config['password'];
- $this->database = $config['database'];
- }
- public function connect() {
- mysql_connect($this->host, $this->username, $this->password);
- }
- public function query() {
- //...code here
- }
- //...more code here
- }
- ?>
class database {
private $host;
private $username;
private $password;
private $database;
public function __construct(array $config) {
$this->host = $config['host'];
$this->username = $config['username'];
$this->password = $config['password'];
$this->database = $config['database'];
}
public function connect() {
mysql_connect($this->host, $this->username, $this->password);
}
public function query() {
//...code here
}
//...more code here
}
?>
private $host;
private $username;
private $password;
private $database;
public function __construct(array $config) {
$this->host = $config['host'];
$this->username = $config['username'];
$this->password = $config['password'];
$this->database = $config['database'];
}
public function connect() {
mysql_connect($this->host, $this->username, $this->password);
}
public function query() {
//...code here
}
//...more code here
}
?>

- $db = new database($config);
- $database->query(“SELECT * FROM users WHERE id = 1”);
$db = new database($config);
$database->query(“SELECT * FROM users WHERE id = 1”);
$database->query(“SELECT * FROM users WHERE id = 1”);
Obviously the code above (assuming the methods have been implemented)will query the database. In most instances the code above is an acceptable practice. However, this will lead you down one of three roads: you will declare $db in the global namespace, you will instantiate a new database object each time it is needed, or you will end up passing $db to object X so when it creates object Y the database object can be passed. Alas, the learned programmer will choose to use the Singleton design pattern.
Solution:
The solution is to create a class that can only be instantiated itself. Moreover, it should not instantiate more than once instance of itself. We start by making the constructor private, creating a new static method which I will call getInstance(), and a new static variable which I will call $instance.

- class database {
- private $host;
- private $username;
- private $password;
- private $database;
- private static $instance;
- private function __construct(array $config) {
- $this->host = $config['host'];
- $this->username = $config['username'];
- $this->password = $config['password'];
- $this->database = $config['database'];
- }
- static function getInstance() {
- }
- public function connect() {
- mysql_connect($this->host, $this->username, $this->password);
- }
- public function query() {
- //...code here
- }
- //...more code here
- }
- ?>
class database {
private $host;
private $username;
private $password;
private $database;
private static $instance;
private function __construct(array $config) {
$this->host = $config['host'];
$this->username = $config['username'];
$this->password = $config['password'];
$this->database = $config['database'];
}
static function getInstance() {
}
public function connect() {
mysql_connect($this->host, $this->username, $this->password);
}
public function query() {
//...code here
}
//...more code here
}
?>
private $host;
private $username;
private $password;
private $database;
private static $instance;
private function __construct(array $config) {
$this->host = $config['host'];
$this->username = $config['username'];
$this->password = $config['password'];
$this->database = $config['database'];
}
static function getInstance() {
}
public function connect() {
mysql_connect($this->host, $this->username, $this->password);
}
public function query() {
//...code here
}
//...more code here
}
?>

- class database {
- private $host;
- private $username;
- private $password;
- private $database;
- //store the instance of this object if one exists
- private static $instance;
- private function __construct(array $config) {
- $this->host = $config['host'];
- $this->username = $config['username'];
- $this->password = $config['password'];
- $this->database = $config['database'];
- }
- static function getInstance(array $config = null) {
- if( empty( self::$instance ) )
- {
- //create a new instance of this class
- self::$instance = new database($config);
- }
- //return the instance
- return self::$instance;
- }
- public function connect() {
- mysql_connect($this->host, $this->username, $this->password);
- }
- public function query() {
- //...code here
- }
- //...more code here
- }
- ?>
class database {
private $host;
private $username;
private $password;
private $database;
//store the instance of this object if one exists
private static $instance;
private function __construct(array $config) {
$this->host = $config['host'];
$this->username = $config['username'];
$this->password = $config['password'];
$this->database = $config['database'];
}
static function getInstance(array $config = null) {
if( empty( self::$instance ) )
{
//create a new instance of this class
self::$instance = new database($config);
}
//return the instance
return self::$instance;
}
public function connect() {
mysql_connect($this->host, $this->username, $this->password);
}
public function query() {
//...code here
}
//...more code here
}
?>
private $host;
private $username;
private $password;
private $database;
//store the instance of this object if one exists
private static $instance;
private function __construct(array $config) {
$this->host = $config['host'];
$this->username = $config['username'];
$this->password = $config['password'];
$this->database = $config['database'];
}
static function getInstance(array $config = null) {
if( empty( self::$instance ) )
{
//create a new instance of this class
self::$instance = new database($config);
}
//return the instance
return self::$instance;
}
public function connect() {
mysql_connect($this->host, $this->username, $this->password);
}
public function query() {
//...code here
}
//...more code here
}
?>

- $db = database::getInstance($config_info);
- $db->connect();
- $db->query(“SELECT * FROM users WHERE id = 1”);
$db = database::getInstance($config_info);
$db->connect();
$db->query(“SELECT * FROM users WHERE id = 1”);
$db->connect();
$db->query(“SELECT * FROM users WHERE id = 1”);
Set as favorite
Bookmark
Email This
Hits: 719
Trackback(0)
Write comment

