单例模式

单例模式

  • 单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例。
  • 不适用单例模式时:
class Database
{
    public $db = null;
    public function __construct($config = array())
    {
        $dsn = sprintf('mysql:host=%s;dbname=%s', $config['db_host'], $config['db_name']);
        $this->db = new PDO($dsn, $config['db_user'], $config['db_pass']);
    }
}

然后创建3个对象:

$config = array(
    'db_name' => 'test',
    'db_host' => 'localhost',
    'db_user' => 'root',
    'db_pass' => 'root'
);

$db1 = new Database($config);
var_dump($db1);
$db2 = new Database($config);
var_dump($db2);
$db3 = new Database($config);
var_dump($db3);
  • 输出信息:
object(Database)[1]
  public 'db' => object(PDO)[2]
object(Database)[3]
  public 'db' => object(PDO)[4]
object(Database)[5]
  public 'db' => object(PDO)[6]
  • 每次new操作都会实例化一次类,就会增加一个数据库的连接,占用内存也在不断增大。
  • 使用单例模式
  • 基类上限制,只能实例化一次,如果实例化过,直接返回。
class Database
{
    // 声明$instance为私有静态类型,用于保存当前类实例化后的对象
    private static $instance = null;
    // 数据库连接句柄
    private $db = null;

    // 构造方法声明为私有方法,禁止外部程序使用new实例化,只能在内部new
    private function __construct($config = array())
    {
        $dsn = sprintf('mysql:host=%s;dbname=%s', $config['db_host'], $config['db_name']);
        $this->db = new PDO($dsn, $config['db_user'], $config['db_pass']);
    }

    // 这是获取当前类对象的唯一方式
    public static function getInstance($config = array())
    {
        // 检查对象是否已经存在,不存在则实例化后保存到$instance属性
        if(self::$instance == null) {
            self::$instance = new self($config);
        }
        return self::$instance;
    }

    // 获取数据库句柄方法
    public function db()
    {
        return $this->db;
    }

    // 声明成私有方法,禁止克隆对象
    private function __clone(){}
    // 声明成私有方法,禁止重建对象
    private function __wakeup(){}
}
  • 实例化使用单利模式
$config = array(
    'db_name' => 'test',
    'db_host' => 'localhost',
    'db_user' => 'root',
    'db_pass' => 'root'
);

$db1 = Database::getInstance($config);
var_dump($db1);
$db2 = Database::getInstance($config);
var_dump($db2);
$db3 = Database::getInstance($config);
var_dump($db3);
  • 输出信息: 获取到的资源ID都是一样的
object(Database)[1]
  private 'db' => object(PDO)[2]
object(Database)[1]
  private 'db' => object(PDO)[2]
object(Database)[1]
  private 'db' => object(PDO)[2]
  • 总结:

单例模式:单利模式在应用中最为常见。单利模式在运行时实例是唯一的,他们不允许被生成自身的副本。 所以 __clone__wakeup等复制克隆对象的魔术方法建议声明为私有方法。 单例模式特点4私1公:

  • 私有静态属性:
  1. private static $instance = null; //用以保存类的实例化
  2. private function __construct(){} // // 构造方法声明为私有方法,禁止外部程序使用new实例化,只能在内部new
  3. private function __clone(){}// // 声明成私有方法,禁止克隆对象
  4. private function __wakeup(){} // // 声明成私有方法,禁止重建对象
  • 公有属性:
//方法提供给外部本类的实例化对象
public static function getInstance()
    {
        if(self::$instance == null) {
            self::$instance = new self();
        }
        return self::$instance;
    }

构造方法私有,克隆方法私有,重建方法私有,一个公共静态方法。