php - 在 PHP 中扩展单例

标签 php inheritance singleton anti-patterns

我在一个 Web 应用程序框架中工作,其中一部分由许多服务组成,所有服务都作为单例实现。它们都扩展了一个 Service 类,其中实现了单例行为,看起来像这样:

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 的类:

class FileService extends Service {
    // Lots of neat stuff in here
}

... 调用 FileService::getInstance() 不会像我想要的那样产生 FileService 实例,而是一个 Service 实例。我认为这里的问题是服务构造函数中使用的“self”关键字。

还有其他方法可以在这里实现我想要的吗?单例代码只有几行,但我仍然希望尽可能避免任何代码冗余。

最佳答案

代码:

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,也添加这个:

// 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 - 在 PHP 中扩展单例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3126130/

相关文章:

ios - 可以拥有单例 UIView 子类吗?

php - MySQL - 仅选择许多图像中的一个(随机)图像

php - 如何在nodejs中实现 "gzencode"(PHP函数)

php - 在 1&1 服务器上部署 Laravel

python - 子类实例化期间出现 AttributeError

java - 关于 Java 子类继承返回 "this"的方法

swift - 在 Swift 中模拟单例/sharedInstance

php - 我如何让这个小 PHP 数组工作?

java - java中一个类的内存分配?

python - 有没有一种简单、优雅的方式来定义单例?