note 82619 deleted from language.oop5.patterns by danbrown
| From: | danbrown@php.net | Date: | Sun, 23 Jan 2011 16:41:26 +0000 |
| Subject: | note 82619 deleted from language.oop5.patterns by danbrown | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-176105@lists.php.net to get a copy of this message | ||
Note Submitter: Chris
----
I cannot belive I was so stupid with my first note on this...
As any Singleton class forces a design pattern on to the user, and is really just a helper class for
that design pattern, there is no reason not to force them to mangle any arguments into an array,
which allows me to get rid of the use of the ReflectionClass and allows protected constructors.
If someone can delete the first note to hide my shame that would be great, and this bit of this one
upto the ----- marker below :D
To save people the trouble of finding my previous note:
-----
This is a Singleton helper class inspired by Mattlock's Singleton class with interface.
It has the advantages of:
1) It uses only a single abstract class instead of an interface and class definition.
2) It allows for multiple instances of classes where you only wish to have one of any instance
initialised with certain arguments such as connections to different databases, they may use the same
class, but there will be one instance for each database.
This method should allow multiple child classes to extend the Singleton class, and only requires a
small about of argument mangling to make it work.
<?php
abstract class Singleton
{
static abstract public function getInstance();
static final protected function getClassInstance($klass, $args=NULL)
{
// Initialize array for $instances
if(self::$instances === NULL)
self::$instances = array();
// Initialize array for instances of $klass
if(!array_key_exists($klass, self::$instances))
self::$instances[$klass] = array();
// Create key from args
$key = serialize($args);
// Instantiate $klass
if(!array_key_exists($key, self::$instances[$klass]))
{
self::$instances[$klass][$key] = new $klass($args);
}
// Return instance of $klass
return self::$instances[$klass][$key];
}
static private
// Storage for all instances of Singleton classes
$instances;
}
final class MySingleton extends Singleton
{
static public function getInstance()
{
return Singleton::getClassInstance(__CLASS__);
}
// Construct should be protected.
protected function __construct() {}
}
final class NamedSingleton extends Singleton
{
public
$name;
// Default arguments here NOT constuctor to prevent dupilicate instances.
static public function getInstance($name = 'Default')
{
// Mangle the arguments into an array
$args = array('name' => $name);
return Singleton::getClassInstance(__CLASS__, $args);
}
// Constructor must accept a single array containing all the arguments, if it wants to get any.
protected function __construct($args)
{
$this->name = $args['name'];
}
}
echo '<pre>';
$a = MySingleton::getInstance();
$b = MySingleton::getInstance();
var_dump($a);
var_dump($b);
$c = NamedSingleton::getInstance();
$d = NamedSingleton::getInstance('Default');
$e = NamedSingleton::getInstance('Default');
var_dump($c);
var_dump($d);
var_dump($e);
echo '</pre>';
?>