Tìm kiếm bài viết

Tìm hiểu Singleton Pattern trong Laravel

21.09.2020

0/5 (0 Reviews)

Singleton Pattern là một mẫu thiết kế (design pattern) được sử dụng để bảo đảm rằng mỗi một lớp (class) chỉ có được một thể hiện (instance) duy nhất và mọi tương tác đều thông qua thể hiện này.

    Tìm hiểu về Singleton pattern trong laravel

    Ở bài trước, mình đã chia sẻ cho các bạn về Template pattern . Hôm nay chúng ta sẽ tìm hiểm về Singleton pattern.

    Singleton Pattern là một mẫu thiết kế (design pattern) được sử dụng để bảo đảm rằng mỗi một lớp (class) chỉ có được một thể hiện (instance) duy nhất và mọi tương tác đều thông qua thể hiện này. Việc áp dụng Singleton pattern vào thiết kế website sẽ đem lại hiệu quả cao trong hiệu xuất website, chỉ số thiết yếu của Google gần đây cũng nhắc đến vấn đền này.

    Singleton Pattern cung cấp một phương thức khởi tạo private, duy trì một thuộc tính tĩnh để tham chiếu đến một thể hiện của lớp Singleton này. Nó cung cấp thêm một phương thức tĩnh trả về thuộc tính tĩnh này.

    Bài toán thực tế áp dụng Singleton Pattern

    Bạn gặp một sự cố về hiệu năng hệ thống. Cùng một thời điểm, các bạn đang sử dụng một lúc nhiều đối tượng và chúng làm tiêu tốn quá nhiều tài nguyên của hệ thống. Đây là vấn đề mà bạn cần phải khắc phục, và Singleton pattern có thể giúp bạn thực hiện được điều đó.

    Tạo một đối tượng duy nhất với mẫu Singleton

    Chúng ta bắt đầu với mẫu Singleton và xử lý rắc rối mà chúng ta vừa gặp phải. Chúng ta muốn chắc chắn rằng chỉ tạo duy nhất 1 đối tượng cho 1 lớp cụ thể dù cho người khác có cố gắng tạo bao nhiêu đối tượng đi nữa.

    Các bạn đang tạo ra hàng trăm đối tượng Database trong mã ngu62n, và rắc rối là từng đối tượng này rất lớn. Đâu là giải pháp? Mấu duy nhất (Singeton pattern) là câu trả lời.

    Mẫu duy nhất Singleton chắc chắn rằng bạn có thể khởi tạo chỉ duy nhất một đối tượng cho một lớp. Nếu bạn không sử dụng mẫu thiết kế này, toán tử new như thường sử dụng, sẽ tạo ra liên tiếp nhiều đối tượng mới như sau: 

    Bạn sử dụng mẫu Singleton khi bạn muốn hạn chế việc sử dụng tài nguyên hoặc khi bạn phải xử lý 1 đối tượng nhạy cảm mà dữ liệu của nó không thể chia sẻ cho mọi thể hiện.

    Bất cứ khi nào bạn thật sự cần duy nhất 1 thể hiện của 1 lớp, hãy nghĩ tới mẫu Singleton thay vì dùng toán tử new.

    Tạo một lớp Database theo kiểu Singleton

    Chúng ta bắt đầu vào xây dựng lớp Database:

    class Database
    {
        private $record;
        private $name;
    
        public function Database($name)
        {
            $this->name = $name;
            $this->record = 0;
        }
        ...
    }
    

    Bạn cần thêm vào 2 hàm editRecord(), cho phép bạn chỉnh sửa 1 bản ghi và hàm getName() để lấy ra tên của Database.

    class Database
    {
        private $record;
        private $name;
    
        public function Database($name)
        {
            $this->name = $name;
            $this->record = 0;
        }
    
        public function getName()
        {
            return $this->name;
        }
    
        public function editRecord($operation)
        {
            return "Performing a " . $operation .
                " operation on record " . $this->record .
                " in database " . $this->name;
        }
    }
    

    Tới giờ mọi việc vẫn tốt đẹp. Bất cứ khi nào bạn tạo 1 đối tượng bằng toán tử new, một đối tượng mới sẽ được tạo ra. Nếu bạn tạo 3 database, bạn sẽ có 3 đối tượng như sau:

    $dataOne = new Database("Product");
    $dataTwo = new Database("Product also");
    $dataThree = new Database("Product again");
    

    Làm sao để bạn có thể tránh việc tạo 1 đối tượng khi mới sử dụng toán tử new? Đây là một giải pháp: làm cho hàm khởi tạo trở nên private:

        private function Database($name)
        {
            $this->name = $name;
            $this->record = 0;
        }
    

    Với cách làm này chúng ta không thể gọi được hàm khởi tạo (contructor) của nó, tức là không thực hiện được dòng lệnh này: $data = new Database(""). Tuy nhiên nếu không gọi được hàm khởi tạo thì làm sao mà ta tạo đối tượng được? Vậy làm sao bạn có thể tạo 1 đối tượng khi bạn không thể gọi hàm khởi tạo nó?

    Do đó chúng ta phải xây dựng 1 hàm nào đó để thay thế cho hàm khở tạo, và khi gọi hàm này thì đối tượng được phát sinh ra theo 1 cách đặc biệt (đặc biệt ở chỗ nếu chưa có đối tượng thì nó sẽ tạo đối tượng mới, còn nếu có rồi thì nó trỏ vào đối tượng đã có rồi, như vậy thì bảo đảm chương trình luôn tồn tại 1 đối tượng). Hàm này thường được đặt tên là getInsstance(). Chú ý rằng hàm này phải được khai báo kiểu publicstatic để bạn có thể truy cập tới nó thông qua tên lớp.

        public static function getInstance($name)
        {
    
        }
    

    Hàm này sẽ trả về một đối tượng Database, nhưng hàm chỉ hoạt động khi có ít nhất một đối tượng đã tồn tại. Vì thế đầu tiên ta cần kiểm tra đối tượng này, nếu đối tượng chưa được khởi tạo thì ta cần khởi tạo nó.

        private static $singletonObject;
    
        public static function getInstance($name)
        {
            if ($this->singletonObject == null) {
                $this->singletonObject = new Database($name);
            }
    
            return $this->singletonObject;
        }
    

    Vấn đề đã được giải quyết. Bây giờ chỉ có duy nhất 1 đối tượng Database tồn tại trong cùng 1 thời điểm. Việc gọi hàm getInstance() sẽ cho ta 1 đối tượng như sau:

    Bây giờ, không quan tâm đến việc bạn gọi bao nhiêu lần hàm getInstance(), bạn luôn nhận được cùng 1 đối tượng. Đó chính là cách bạn làm với mẫu Singleton.

    Chạy thử ví dụ với mẫu Singleton

    Bắt đầu bằng việc tạo một đối tượng Database với tên là products, sau đó gọi hàm getName():

    $database = Database::getInstance("Product");
    echo "This is the " . $database->getname() . " database.";
    

    Sau đó bạn tiếp tục tạo 1 đối tượng Database với tên là employees, và gọi lại hàm getName() để kiểm tra:

    $database = Database::getInstance("Employees");
    echo "This is the " . $database->getname() . " database.";
    

    Tuy nhiên, đối tượng Database đã được tạo, vì vậy trong lần thứ 2, hàm getInstance () vẫn trả về đối tượng Database cũ.

    Vậy là bạn đã nhận được duy nhất 1 đối tượng cho dù đã thực hiện việc tạo 2 lần. Cách thức bạn làm vệc như sau: ngăn cản việc khởi tạo bằng toán tử new, và tạo 1 hàm để tạo đối tượng theo ý bạn. Đó chính là cách hoạt động của mẫu Singleton

    Vậy là chúng ta vừa tìm hiểu xong về Singleton Pattern. Hy vọng bài viết sẽ giúp ích cho các bạn trong việc lập trình. 

    CÓ THỂ BẠN QUAN TÂM

    Bài Viết Cùng Chuyên Mục

    XEM THÊM
    thumbnail

    Kubernetes bài 6 - Vận hành k8s Day-Two Operations và Quản trị bằng GitOps

    22.05.2026

    Khi cụm Kubernetes của bạn đã được bảo mật cấu hình, tối ưu tài nguyên và thiết lập tự phục hồi, câu hỏi đặt ra là làm sao để duy trì sự ổn định đó trong nhiều năm tiếp theo mà không bị phụ thuộc

    thumbnail

    Kubernetes bài 5 - bảo mật Cloud Native và chuẩn DevSecOps cho K8s

    22.05.2026

    Việc siết chặt an ninh (Hardening) không phải là cấu hình một vài thông số rồi bỏ đó, mà là một tư duy phòng thủ chiều sâu.

    thumbnail

    Kubernetes bài 4 - Tối ưu Resource Auto-Healing và Scale Zero-Downtime

    22.05.2026

    Bài viết này sẽ đi sâu vào các cơ chế ở tầng Kernel giúp hệ thống tự phục hồi, chống lại các đợt tấn công cạn kiệt tài nguyên và cập nhật phiên bản mới mà người dùng không hề hay biết.

    thumbnail

    Kubernetes bài 3 - Bảo mật cấu hình k8s và config Security trên Production

    22.05.2026

    Kubernetes giải quyết bài toán này bằng hai đối tượng chuyên biệt nhưng nếu không hiểu rõ bản chất bảo mật ở tầng dưới, bạn đang tự tay dâng toàn bộ chìa khóa hệ thống cho hacker.

    thumbnail

    Kubernetes bài 2 - Mạng lưới k8s và luồng Traffic ở Packet Level

    22.05.2026

    Pod không chỉ là một container: Rất nhiều người nhầm lẫn Pod 1-1 với Container. Thực chất, Pod là đơn vị triển khai nhỏ nhất, có thể chứa một hoặc nhiều container

    Mục lục bài viết