note 82617 deleted from language.oop5.patterns by danbrown
| From: | danbrown@php.net | Date: | Sun, 23 Jan 2011 16:41:32 +0000 |
| Subject: | note 82617 deleted from language.oop5.patterns by danbrown | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-176106@lists.php.net to get a copy of this message | ||
Note Submitter: Chris
----
This is an extension to Mattlock's Singleton class and interface.
It has a number of advantages:
1) It uses a single abstract class instead of an interface and class definition, which to me is
cleaner.
2) It allows for multiple instances of one class where you only wish to have one of any instance
initialised with certain arguments. For example a File class representing a file on the system,
there will be multiple files, but you will only want one instance of the File class for each
individual file.
but a number of disadvantages:
1) The use of ReflectionClass is far from ideal, but I cannot find a better way to initialise an
"unknown" class with arguments to the constructor, without requiring another
'utility' method in the child class.
2) The __construct method of child classes MUST be declared 'public' so that the
ReflectionClass can instantiate it.
if there is a good way to instantiate a class in a function that has its name as a string and an
array holding its arguments, without using eval etc, please tell me :D
<?php
abstract class Singleton
{
static abstract public function getInstance();
static final protected function getClassInstance($klass)
{
// Initialize array for $instances
if(self::$instances === NULL)
self::$instances = array();
// Get arguments and remove $klass
$args = func_get_args();
array_shift($args);
// Create key from args
$key = serialize($args);
// Initialize array for instances of $klass
if(!array_key_exists($klass, self::$instances))
self::$instances[$klass] = array();
// Instantiate $klass using reflection and store under $key
if(!array_key_exists($key, self::$instances[$klass]))
{
if(count($args) > 0)
{
$reflect = new ReflectionClass($klass);
self::$instances[$klass][$key] = $reflect->newInstanceArgs($args);
}
else
{
// ReflectionClass cannot pass arguments to classes with no constructor.
self::$instances[$klass][$key] = new $klass();
}
}
// Return instance of $klass
return self::$instances[$klass][$key];
}
static private
// Storage for all instances of Singleton classes
$instances;
}
class MySingleton extends Singleton
{
static public function getInstance()
{
return Singleton::getClassInstance(__CLASS__);
}
}
class ArgSingleton extends Singleton
{
public
$arg;
// Default arguments here NOT constuctor to prevent dupilicate instances.
static public function getInstance($arg = 'Default')
{
return Singleton::getClassInstance(__CLASS__, $arg);
}
public function __construct($arg)
{
$this->arg = $arg;
}
}
echo '<pre>';
$a = MySingleton::getInstance();
$b = MySingleton::getInstance();
var_dump($a);
var_dump($b);
$c = ArgSingleton::getInstance();
$d = ArgSingleton::getInstance('Default');
$e = ArgSingleton::getInstance('Default');
var_dump($c);
var_dump($d);
var_dump($e);
echo '</pre>';
?>