一个更简单的单身人士

时间:2011-09-10 00:01:35

标签: php

我见过的所有单例模式都使用对象的引用来确定对象是否已被实例化。但是,如果我使用单例来保证只有一个数据库连接,为什么不使用数据库连接资源链接来执行此操作?这是我正在使用的代码。 (PS:它工作正常)。我使用评论可以轻松搜索我的课程。

/*one*/

class one
  {
  public static $db;
  private function __construct()
    {
    self::$db=new mysqli(DB_HOST, DB_USER, DB_PASS, DB_DATABASE);
    }
  public static function get()
    {
    if(self::$db==NULL)
      {
      new self();
      }
    return self::$db;
    }
  }

5 个答案:

答案 0 :(得分:5)

在PHP中,构造函数不会返回。

因此,get方法在第一次调用时返回one个对象,然后返回mysqli个对象。可能不是你想要的。

if( self::$_db == NULL )
{
    return new self(); // Here you return an object of class one
}
else
{
    return self::$_db; // Here you return an object of type mysqli
}

如果要返回mysqli对象,则不需要单例,因为不需要创建仅在此处返回另一个对象实例的对象实例。

在这种情况下,注册表模式会更好。

如果需要提供方法(数据库对象的包装器),则创建一个真正的单例。

修改

我检查了您的更新代码。 现在,您始终返回mysqli实例。但是您不需要实例化自己的对象。那完全没用......

如果你真的想要使用你的那种模式,正如黄金所说,在你的静态实例中,检查self::dbNULL。如果是,则创建mysqli实例,并将其分配给self::db。然后返回它。

public static getDatabaseInstance()
{
    if( self::$_db == NULL )
    {
        self::$_db = new mysqli( ... );
    }

    return self::$_db;
}

还将构造函数设置为私有,因此用户将无法创建类的无用实例。或者更好地公开并抛出异常:

public function __construct()
{
    throw new Exception( 'This class is not supposed to be instantiated' );
}

答案 1 :(得分:3)

定义它可以正常工作:)

尝试:

  • 比较两种方法返回的对象哈希值(使用对象克隆时很重要)
  • 使用不同凭据连接到数据库(例如,在单元测试中)
  • 断开与DB的连接并重新连接
  • 重置对象的实例(现在使用new创建1000个对象填充内存)
  • 告诉其他开发人员在这个类的实例中创建,他肯定会寻找one::getInstance()方法。他如何猜测这门课的行为?

单身人士是关于全球的国家。看起来在这里你有全球状态+一些混乱。

答案 2 :(得分:1)

假设我正确地解析了你的问题,你会问是否可以使用$db的无效来确保你只实例化一个;这是一种非常有效的做事方式,实际上是我推荐的方式。 PHP null明确用于表示“无值”的变量 - 非常适合单例模式的未初始化状态。

通常情况下,这些事情只会通过直观的名称来调用,例如: SomeAppDbConn

答案 3 :(得分:0)

class one
{
    private static $_selfInstance;
    public $db;
    private function __construct()
    {
    }
    public function getDb()
    {
      if($this->db == null)
      $this->db=new mysqli(DB_HOST, DB_USER, DB_PASS, DB_DATABASE);
      return $this->db;

    }

    public static function getInstance()
    {
      if( !(self::$_selfInstance instanceof self) ) {
        self::$_selfInstance= new self();
      }
      return self::$_selfInstance;
    }
}

访问

$db = one::getInstance()->getDb();

答案 4 :(得分:0)

正如Macmade已经指出的那样,constructor方法除了返回类的实例外不会返回任何内容。假设你总是想要mysqli的同一个实例,我就是这样做的。

class DBInstance
{
    protected static $db;

    private function __construct()
    {
        // intentionally empty
    }

    public static function get()
    {
        if(self::$db === NULL)
        {
            self::$db=new mysqli(DB_HOST, DB_USER, DB_PASS, DB_DATABASE);
        }

        return self::$db;
    }
}

它肯定是一个单例模式,还有将实例化与实例化类分开的额外好处。