Tìm hiểu Singleton Pattern

Tìm hiểu về Singleton pattern.

Bài viết được tham khảo từ cuốn Design pattern for dummies

Ở bài trước, mình đã giới thiệu cho các bạn về Template pattern: https://viblo.asia/trung.nn.92/posts/ZabG91kkGzY6. 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.

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ế

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: 1.PNG

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 public và static để 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. 😄

Related Posts

Xét nghiệm Giải phẫu bệnh – Dẫn đường cho việc điều trị

Xét nghiệm giải phẫu bệnh được thực hiện trên những mẫu bệnh phẩm tế bào, bệnh phẩm mô từ các cơ quan trong cơ thể được sinh…

Phương pháp điều trị tủy răng tại nha khoa hiện nay

Viêm tủy răng là một trong những vấn đề về sức khỏe răng miệng nghiêm trọng. Người mắc viêm tủy răng không chỉ phải chịu đựng những…

Mỹ thuật ứng dụng là gì? (cập nhật 2023)

Khi những giá trị thẩm mỹ ngày càng được chú trọng thì các phẩm mỹ thuật ứng dụng ngày càng đi sâu vào đời sống của mọi…

Bát quái đồ là gì? Ý nghĩa và vai trò của bát quái trong phong thủy

Bát quái đồ là vật phẩm phong thủy được sử dụng khá rộng rãi và phổ biến trong văn hoá phương Đông, nhằm mang lại những niềm…

Du học ngành khoa học ứng dụng và cơ bản

>> Du học ngành khoa học đại cương >> Các trường có đào tạo ngành Khoa học ứng dụng và cơ bản Khoa học Ứng dụng và…

Trồng răng implant là gì? Những điều cần phải biết trước khi chọn trồng răng implant

Trồng răng implant là phương pháp trồng răng cấy trụ kim loại vào xương hàm để thay thế cho răng đã mất. Chính vì vậy trụ implant…