用PHP扩展单例 [英] Extending singletons in PHP
问题描述
我正在使用Web应用程序框架,其中一部分由许多服务组成,所有服务都以单例形式实现。它们都扩展了一个Service类,其中实现了单例行为,如下所示:
I'm working in a web app framework, and part of it consists of a number of services, all implemented as singletons. They all extend a Service class, where the singleton behaviour is implemented, looking something like this:
class Service {
protected static $instance;
public function Service() {
if (isset(self::$instance)) {
throw new Exception('Please use Service::getInstance.');
}
}
public static function &getInstance() {
if (empty(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
}
}
现在,如果我有一个名为FileService的类实现像这个:
Now, if I have a class called FileService implemented like this:
class FileService extends Service {
// Lots of neat stuff in here
}
...调用FileService :: getInstance()不会产生FileService实例,就像我想要的那样,但是一个服务实例。我假设这里的问题是服务构造函数中使用的self关键字。
... calling FileService::getInstance() will not yield a FileService instance, like I want it to, but a Service instance. I assume the problem here is the "self" keyword used in the Service constructor.
还有其他方法可以实现我想要的吗?单例代码只有几行,但我仍然希望尽可能避免任何代码冗余。
Is there some other way to achieve what I want here? The singleton code is only a few lines, but I'd still like to avoid any code redundance whenever I can.
推荐答案
代码:
abstract class Singleton
{
protected function __construct()
{
}
final public static function getInstance()
{
static $instances = array();
$calledClass = get_called_class();
if (!isset($instances[$calledClass]))
{
$instances[$calledClass] = new $calledClass();
}
return $instances[$calledClass];
}
final private function __clone()
{
}
}
class FileService extends Singleton
{
// Lots of neat stuff in here
}
$fs = FileService::getInstance();
如果您使用PHP< 5.3,添加它:
If you use PHP < 5.3, add this too:
// get_called_class() is only in PHP >= 5.3.
if (!function_exists('get_called_class'))
{
function get_called_class()
{
$bt = debug_backtrace();
$l = 0;
do
{
$l++;
$lines = file($bt[$l]['file']);
$callerLine = $lines[$bt[$l]['line']-1];
preg_match('/([a-zA-Z0-9\_]+)::'.$bt[$l]['function'].'/', $callerLine, $matches);
} while ($matches[1] === 'parent' && $matches[1]);
return $matches[1];
}
}
这篇关于用PHP扩展单例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!