[PHP] Design Pattern: Singleton

Singleton là pattern đảm bảo việc một ứng dụng trong một thời điểm chỉ được phép có duy nhất một thực thể của đối tượng Singleton.
Có nghĩa là việc khởi tạo đối tượng chỉ duy nhất một lần đầu tiên, các lần sau, nó không được khởi tạo mới mà chính là đối tượng cũ. Điều này giúp tiết kiệm bộ nhớ và ngăn chặn việc tạo ra nhiều lần khởi tạo đối tượng. Trong bài này mình sẽ giới thiệu về Singleton trong PHP

Lưu ý

Pattern này đang gây nhiều tranh cãi nó là pattern hay anti-pattern. Để code testabilitymaintainability thì nên sử dụng Dependency Injection.
enter image description here

Sử dụng khi nào?

Khi trong ứng dụng có những thực thể bị truy xuất nhiều lần nhưng không cần thiết phải khởi tạo lại. Ví dụ:
  • Database connect: nếu không dùng Singleton, mỗi lần muốn thao tác với db, chúng ta cần phải khởi tạo lại lớp Database
  • Logger: trong ứng dụng, có nhiều chỗ cần phải lưu log, hãy tưởng tượng nếu không dùng Singleton, mỗi lần muốn lưu log lại phải khởi tạo lại lớp Logger
  • Đọc config file: bạn có một file chứa nhiều thông số config. Nếu không dùng Singleton, mỗi lần muốn đọc một thông số nào đó, bạn lại phải khởi tạo lại.

Xây dựng

Để xây dựng Singleton, bạn cần đáp ứng được các yêu cầu sau:
  • Define thuộc tính (biến) private static $instance
  • Define public static function getInstance() trả về instance theo dạng lazy initialization (khởi tạo trong lần đầu).
  • Define __construct() thành protected hoặc private để ngăn người dùng khởi tạo trực tiếp.
class Singleton
{
    private static $instance;

    private function __construct()
    {
    }

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

Ví dụ

class Singleton
{
    private static $instance;

    private function __construct()
    {
    }

    public static function getInstance()
    {
        if (null === static::$instance) {
            static::$instance = new static;
            echo 'new';
            return static::$instance;
        }
        echo 'old';
        return static::$instance;
    }
}

$singleton = Singleton::getInstance(); // new
$singleton = Singleton::getInstance(); // old
$singleton = Singleton::getInstance(); // old
Sử dụng Singleton sẽ tiết kiệm bộ nhớ vì không tạo ra nhiều objects, quản lý thread, flow dễ hơn. Tuy nhiên để code testabilitymaintainability thì nên sử dụng Dependency Injection.