PHP中的单例模式

3
class SingleTon
{
    private static $instance;

    private function __construct()
    {
    }

    public function getInstance() {
        if($instance === null) {
            $instance = new SingleTon();
        }
        return $instance;
    }
}

以下代码展示了这篇文章中的单例模式。 http://www.hiteshagrawal.com/php/singleton-class-in-php-5 我不明白一件事情,如果我把这个类加载到我的项目中,我该如何最初创建一个Singleton对象呢?我会像这样调用吗:Singelton::getInstance()
有人能给我展示一个已经建立数据库连接的Singleton类吗?

1
if($instance === null) { $instance = new SingleTon(); } 的哪个部分让您不清楚?(注意:应为 Singleton,而非 SingleTon、Singelon 或 Singelton) - Piskvor left the building
5个回答

14

以下是一个实现数据库类单例模式的示例:

class Database implements Singleton {
    private static $instance;
    private $pdo;

    private function __construct() {
        $this->pdo = new PDO(
            "mysql:host=localhost;dbname=database",
            "user",
            "password"
        );
    }

    public static function getInstance() {
        if(self::$instance === null) {
            self::$instance = new Database();
        }
        return self::$instance->pdo;
    }
}

您可以按以下方式使用该类:

$db = Database::getInstance();
// $db is now an instance of PDO
$db->prepare("SELECT ...");

// ...

$db = Database::getInstance();
// $db is the same instance as before

作为参考,Singleton 接口应该是这样的:

interface Singleton {
    public static function getInstance();
}

在建议的代码中,Database::getInstance() 中的 getInstance 应该是 静态的。同样,在 Java 的单例模式中,getInstance 方法也总是静态的。静态方法返回类的方法,公共(非静态)方法返回实例的方法。 - Mitja Gustin
所有的可爱和惹人喜爱,但私有/受保护的构造函数对我不起作用。我尝试使用这种方式实例化PDO时出现了这个错误:Access level to Database::__construct() must be public (as in class PDO) - Klemen Tusar
@techouse:我已经更新了我的答案。现在应该能够为您工作了。 - user142162
@TimCooper 工作正常 :) 我建议将 PDO 实例化封装在 try ... catch 块中,并在出现问题时抛出 Exception 异常 :) - Klemen Tusar
@techouse:我只是让异常冒泡; 让调用Database :: getInstance的人来处理它。 - user142162
显示剩余5条评论

1

是的,你必须使用调用

SingleTon::getInstance();

第一次运行时,它将测试私有变量$instance是否为空,因此脚本将运行$instance = new SingleTon();

对于数据库类来说,情况也是一样的。这是我在Zend Framework中使用的一个类的摘录:

class Application_Model_Database
{
   /**
    *
    * @var Zend_Db_Adapter_Abstract
    */
   private static $Db = NULL;

   /**
    *
    * @return Zend_Db_Adapter_Abstract
    */
   public static function getDb()
   {
      if (self::$Db === NULL)
         self::$Db = Zend_Db_Table::getDefaultAdapter();
      return self::$Db;
   }
}

注意:模式是Singleton,而不是SingleTon。


0
class Database{
    private static $link=NULL;
    private static $getInitial=NULL;

    public static function getInitial() {
         if (self::$getInitial == null)
         self::$getInitial = new Database();
         return self::$getInitial;
    }
    public function __construct($server = 'localhost', $username = 'root', $password ='tabsquare123', $database = 'cloud_storage') {

         self::$link = mysql_connect($server, $username, $password);
         mysql_select_db($database,self::$link);
         mysql_query("SET CHARACTER SET utf8", self::$link); 
         mysql_query("SET NAMES 'utf8'", self::$link); 
         return self::$link;
    }

    function __destruct(){
          mysql_close(self::$link);
    }
}

你能否尝试并发布一些你编写代码的解释吗? - NREZ

0
一些关于你代码的修改。你需要确保getInstance方法是“静态”的,这意味着它是一个类方法而不是实例方法。你还需要通过使用'self'关键字引用属性。
虽然通常不会这样做,但你也应该重写“__clone()”方法,以避免实例被克隆。
<?
class Singleton
{
    private static $_instance;

    private function __construct() { }
    private final function __clone() { }

    public static function getInstance() {
        if(self::$_instance === null) {
            self::$_instance = new Singleton();
        }
        return self::$_instance;
    }
}
?>

$mySingleton = Singleton::getInstance();

需要注意的一点是,如果您计划进行单元测试,使用单例模式会带来一些困难。请参见http://sebastian-bergmann.de/archives/882-Testing-Code-That-Uses-Singletons.html


0
自从PHP 7.4中添加了null合并运算符,最简单的单例模式可以如下所示:
class Singleton
{
    private function __construct()
    {
    }

    public static function getInstance(): self
    {
        static $instance;
        return $instance ??= new self();
    }
}

在PHP 8.0中,当添加了静态返回类型时,可以用static来替代self,以允许单例类在不重写getInstance()方法的情况下进行扩展。
class Singleton
{
    private function __construct()
    {
    }

    public static function getInstance(): static
    {
        static $instance;
        return $instance ??= new static();
    }
}
$instance变量可以是局部变量或类属性。这取决于你是否需要在getInstance()方法之外访问它。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接