note 88429 deleted from language.oop5.patterns by danbrown

From: Date: Fri, 23 Jan 2009 17:24:02 +0000
Subject: note 88429 deleted from language.oop5.patterns by danbrown
References: 1  Groups: php.notes 
Request: Send a blank email to php-notes+get-149706@lists.php.net to get a copy of this message
Note Submitter: Anonymous ---- Hello vaddsm! Your trick is rather clever, but it does not actually produce classes that implement the singleton pattern. There is nothing to prevent you (or another programmer on your development team) from simply doing the following: <?php new fClassTwo(); new fClassTwo(); ?> . . . which would create two separate instances of the class fClassTwo. Additionally, instantiating two instances of fSingleton would allow multiple instances of its client classes to be created as well, as follows: <?php $factory1 = new fSingleton(); $factory2 = new fSingleton(); $factory1->fClassTwo->get(); $factory2->fClassTwo->get(); ?> I think the following solution that does the same thing is slightly more clear and helps prevent accidental multiple instantiation better, by making the factory itself a singleton: <?php class CachedInstanceFactory { private static $instance; private static $classes; public static function getInstance() { if (null == self::$instance): $className = __CLASS__; self::$instance = new $className(); endif; return self::$instance; } private function __construct() { $this->$classes = array(); } public function getClass($name) { if ( ! array_key_exists($name, $this->classes) ): $this->classes[$name] = new $name(); endif; return $this->classes($name); } } ?> Usage might be as follows: <?php $factory = CachedInstanceFactory::getInstance(); $factory->getClass('fClassTwo'); $factory->getClass('fClassTwo'); ?> Note, however, that the preceding still doesn't address the fact that if fClassTwo (for instance) is not a singleton, then it can always be created twice as follows: <?php new fClassTwo(); new fClassTwo(); ?> In the past I have used code similar to this to instantiate only one instance of a database connection class for every unique set of database connection credentials supplied (i.e. username, password, host, and port). However, in that case, the logic was built into the database connection class itself (not a factory class), so that the database connection class was similar to a singleton in concept and code, but not exactly a singleton per se. It allowed multiple instances of itself to exist, provided that the database connection did not already exist (and therefore allowed connecting to multiple databases simultaneously without constantly disconnecting from one and reconnecting to the other, as a proper singleton would probably be implemented). It also prevented any accidental copies of itself from coming into existence via the "new" and "clone" operators. (Please ignore any minor syntax or logic bugs in this note, as I am not near a computer with PHP installed at the moment.)

« previous php.notes (#149706) next »