Singleton
Khi thiết kế một ứng dụng web, Thường bạn chỉ muốn cho phép truy cập tới một và chỉ một đối tượng của class cụ thể. Singleton pattern sẽ giúp bạn làm điều đó.
<?php
class Singleton
{
/**
* @var Singleton The reference to *Singleton* instance of this class
*/
private static $instance;
/**
* Returns the *Singleton* instance of this class.
*
* @return Singleton The *Singleton* instance.
*/
public static function getInstance()
{
if (null === static::$instance) {
static::$instance = new static();
}
return static::$instance;
}
/**
* Protected constructor to prevent creating a new instance of the
* *Singleton* via the `new` operator from outside of this class.
*/
protected function __construct()
{
}
/**
* Private clone method to prevent cloning of the instance of the
* *Singleton* instance.
*
* @return void
*/
private function __clone()
{
}
/**
* Private unserialize method to prevent unserializing of the *Singleton*
* instance.
*
* @return void
*/
private function __wakeup()
{
}
}
class SingletonChild extends Singleton
{
}
$obj = Singleton::getInstance();
var_dump($obj === Singleton::getInstance()); // bool(true)
$anotherObj = SingletonChild::getInstance();
var_dump($anotherObj === Singleton::getInstance()); // bool(false)
var_dump($anotherObj === SingletonChild::getInstance()); // bool(true)
Đọan code trên thực thi singleton pattern sử dụng biến static và
phương thức static getInstance()
. Note the following:
- Hàm constructor
__construct()
được khai báo protected để ngăn chặn tạo đối tượng mới bên ngoài class bằng toán tửnew
. - Phương thức magic
__clone()
được khai báo
private để ngăn chặn sao chép đối tượng của class bằng toán tửclone
. - Phương thức magic
__wakeup()
được khai báo private để ngăn không cho unserializing đối tượng của class từ hàm globalunserialize()
. - Một đối tượng mới sẽ được tạo từ một liên kết static trễ trong phương thức static
getInstance()
với từ khóastatic
, cho phép sự phân lớp của classSingleton
trong ví dụ.
Singleton pattern hữu ích khi chỉ một đối tượng được tạo từ một class trong toàn thời gian của một request trong một ứng dụng web. Đặc trưng là khi bạn có các đối tượng toàn cục (như class Config) hay các tài nguyên được chia sẻ.
Bạn nên cẩn thận khi dùng Singleton bởi vì nó nó làm giảm khả năng test. Trong nhiều trường hợp dependency injection có thể (và nên) được dùng taại vị trí của class singleton. Sử dụng dependency injection có nghĩa bạn không giới thiệu coupling không cần thiết vào thiết kế của ứng dụng, bởi vì đối tượng sử dụng các tài nguyên toàn cục hay tài nguyên được chia sẻ không cần sự hiểu biết của class được khai báo cụ thể.