One Step Closer to an Abstract Singleton
The singleton is an incredibly useful pattern in PHP for many reasons. I tend to find myself using them when I know I should be using static classes, but can’t because of PHP’s lack of proper class name discovery in extended static classes. Also, they make great containers for database connections, configuration objects, session wrappers, and anything else that should only live once every page load.
The typical singleton pattern in PHP looks like the following:
<?php class Panda_Singleton { private $Instance; private final function __construct() {} private final function __clone() {} public static function getInstance() { if (self::$Instance === null) { self::$Instance = new self; } return self::$Instance; } } ?>
And that works like a charm every time. The problem is, in one application there may be several classes that need to be singletons. In which case my first thought was to build an abstract singleton. If you have ever tried this, you know my frustration when it didn’t work.
I did however, come up with this:
<?php interface Panda_Singleton_Interface { public static function getInstance(); } abstract class Panda_Singleton implements Panda_Singleton_Interface { protected final function __construct() {} private final function __clone() {} } ?>
Which leaves you to implement the $Instance property and the getInstance method. This bugged me because I didn’t want a $Instance floating around in all my concrete classes if I didn’t need to.
Fortunately PHP supports static variables outside of class scope — like in function scope, for example. Or in this case, a class method:
That is all that needs to be implemented in concrete classes. Sure, it’s not really much better than what what we were doing before, nor is it any more elegant. But I have found myself using this technique to save a few keystrokes from time to time.
3 Responses to One Step Closer to an Abstract Singleton
Adeel Shahid:
Why don’t you skip our creating an interface and instead create a abstract class leaving out getInstance() that should save you a few more key stokes.
I have read about singletons, I am though a beginner but what I realize is people use singleton to bring control to application state, while Singleton’s role should remain bound to sharing state not control and that sharing state should happen using an interface rather then core Singleton objects which introduce strong coupling, harder to debug and test and most importantly bringing upgrade to your application.
Adeel Shahid:
I have written some code to expand on idea of Abstract Patterns comments in code explain the stuff.
interface iPreference {
public function getProperty($key);
public function setProperty($key, $value);
}
final class Preference implements iPreference {
private static $instance;
private $properties;
private function __construct() { }
private function __clone() { }
public static function getInstance() {
if (empty(self::$instance) || !(self::$instance instanceof self)) {
self::$instance = new Preference();
}
return self::$instance;
}
/** Implementing iPreference interface */
public function getProperty($key) {
if (isset($this->properties[$key])) {
return $this->properties[$key];
}
throw new Exception(’property not found’);
}
public function setProperty($key, $value) {
$this->properties[$key] = $value;
}
}
$pObj = Preference::getInstance();
$pObj->setProperty(’color’, ‘yellow’);
/**
* Now when passing Preference object $pObj to another class or constructor
* that class or constructor should accept $pObj as a IPreference
* helping you flexibly change Singleton later on if you run into extensibility problems
*/
developercast.com » Michael Girouard’s Blog: One Step Closer to an Abstract Singleton:
On November 27th, 2007 at 10:45 am #
[...] Girouard has pointed out that things in the PHP world are one step closer to being able to create an abstract Singleton [...]