Trước tiên, chúng ta hãy cùng cafedev giới thiệu mọi thức về Singleton Design Pattern và phần code ví dụ chi tiết nhằm giúp ace dễ hiểu khi áp dụng trên các ngôn ngữ khác nhau. Ace có thể tham khảo thêm các bài khác tại series Design Pattern tại đây.

1. Singleton Design Pattern là gì?

Singleton là một phần Gang of Four design pattern và nó được phân loại theo các creational design patterns. Trong bài viết này, chúng ta sẽ đi sâu hơn vào việc sử dụng Singleton pattern. Đây là một trong những Design Pattern đơn giản nhất về mặt mô hình nhưng mặt khác, đây là một trong những pattern gây tranh cãi nhiều nhất về độ phức tạp khi sử dụng.

Singleton pattern là một Design Pattern hạn chế khởi tạo lớp với nhiều đối tượng của nó. Nó không là gì khác ngoài một cách khai báo lớp. Lớp được định nghĩa theo cách mà chỉ một thể hiện của lớp được tạo ra trong quá trình thực thi hoàn chỉnh một chương trình hoặc dự án. Nó được sử dụng khi chỉ cần một thể hiện duy nhất của một lớp để kiểm soát hành động trong suốt quá trình thực thi. Một lớp singleton không nên có nhiều trường hợp trong mọi trường hợp và bằng mọi giá. Các lớp Singleton được sử dụng để ghi nhật ký, đối tượng trình điều khiển, bộ nhớ đệm và nhóm luồng, kết nối cơ sở dữ liệu.

2. Triển khai lớp Singleton

Triển khai của lớp singleton phải có các thuộc tính sau:

  1. Nó chỉ nên có một thể hiện:  Điều này được thực hiện bằng cách cung cấp một thể hiện của lớp từ bên trong lớp. Các lớp bên ngoài hoặc lớp con nên được ngăn chặn để tạo các instance khác. Điều này được thực hiện bằng cách đặt phương thức khởi tạo là private trong java để không lớp nào có thể truy cập phương thức khởi tạo và do đó không thể khởi tạo nó.
  2. Thể hiện phải có thể truy cập toàn cầu:  Thể hiện của lớp singleton phải có thể truy cập được trên toàn cầu để mỗi lớp có thể sử dụng nó. Trong Java, nó được thực hiện bằng cách công khai thông số truy cập của instance.

3. Các kiểu khởi tạo của Singleton

  1. Lớp Singleton có thể được khởi tạo bằng hai phương thức:

Khởi tạo sớm(Early initialization): Trong phương thức này, lớp được khởi tạo cho dù nó có được sử dụng hay không. Ưu điểm chính của phương pháp này là tính đơn giản của nó. Bạn khởi tạo lớp tại thời điểm tải lớp. Hạn chế của nó là lớp luôn được khởi tạo cho dù nó đang được sử dụng hay không.

Khởi tạo lười biếng(Lazy initialization): Trong phương thức này, lớp trong chỉ được khởi tạo khi nó được yêu cầu. Nó có thể giúp bạn không phải khởi tạo lớp học khi bạn không cần. Nói chung, khởi tạo lười biếng được sử dụng khi chúng ta tạo một lớp singleton.

4. Ví dụ về lớp Singleton

  1. java.lang.Runtime: Java cung cấp một lớp Runtime trong gói lang của nó, bản chất là singleton. Mọi ứng dụng Java đều có một phiên bản Runtime của lớp cho phép ứng dụng giao tiếp với môi trường mà ứng dụng đang chạy. Thời gian chạy hiện tại có thể được lấy từ phương thức getRuntime().
    Một ứng dụng không thể khởi tạo lớp này nên không thể tạo nhiều đối tượng cho lớp này. Do đó Runtime là một lớp singleton.
  2. java.awt.Desktop: Lớp Desktop cho phép ứng dụng Java khởi chạy các ứng dụng liên quan được đăng ký trên màn hình để xử lý URI hoặc file.
    Các hoạt động được hỗ trợ bao gồm:
    • khởi chạy trình duyệt mặc định của người dùng để hiển thị một URI được chỉ định 
    • khởi chạy ứng dụng mail người dùng mặc định với một URI tùy chọn là mailto
    • khởi chạy ứng dụng đã đăng ký để mở, chỉnh sửa hoặc in một tệp được chỉ định.
    • Lớp này cung cấp các phương thức tương ứng với các thao tác này. Các phương pháp tìm kiếm ứng dụng liên quan được đăng ký trên nền tảng hiện tại và khởi chạy nó để xử lý URI hoặc tệp. Nếu không có ứng dụng nào được liên kết hoặc ứng dụng được liên kết không được khởi chạy, một ngoại lệ sẽ được đưa ra.
    • Mỗi thao tác là một kiểu hành động được đại diện bởi lớp Desktop.Action.
  3. Lớp này cũng không thể được khởi tạo từ ứng dụng. Do đó nó cũng là một lớp singleton.

Ứng dụng của các lớp Singleton

Có rất nhiều ứng dụng của mô hình singleton như bộ nhớ đệm, kết nối cơ sở dữ liệu, trình điều khiển, ghi nhật ký. Một số chính trong số họ là: –

  1. Truy cập giao diện phần cứng: Việc sử dụng singleton tùy thuộc vào yêu cầu. Các lớp Singleton cũng được sử dụng để ngăn chặn truy cập đồng thời của lớp. Thực tế, singleton có thể được sử dụng trong trường hợp yêu cầu giới hạn sử dụng tài nguyên phần cứng bên ngoài, chẳng hạn như máy in phần cứng nơi bộ đệm in có thể được tạo thành một singleton để tránh nhiều truy cập đồng thời và tạo ra bế tắc.
  2. Logger: Các lớp Singleton được sử dụng trong các thế hệ tệp nhật ký. Các tệp nhật ký được tạo bởi đối tượng lớp trình ghi nhật ký. Giả sử một ứng dụng trong đó tiện ích ghi nhật ký phải tạo một tệp nhật ký dựa trên các thông báo nhận được từ người dùng. Nếu có nhiều ứng dụng khách sử dụng lớp tiện ích ghi nhật ký này, chúng có thể tạo nhiều bản sao của lớp này và nó có thể gây ra sự cố trong quá trình truy cập đồng thời vào cùng một tệp trình ghi nhật ký. Chúng ta có thể sử dụng lớp tiện ích ghi nhật ký như một lớp đơn và cung cấp một điểm tham chiếu chung để mỗi người dùng có thể sử dụng tiện ích này và không có 2 người dùng nào truy cập nó cùng một lúc.
  3. Tệp cấu hình: Đây là một ứng cử viên tiềm năng khác cho mẫu Singleton vì điều này có lợi ích về hiệu suất vì nó ngăn nhiều người dùng truy cập liên tục và đọc tệp cấu hình hoặc tệp thuộc tính. Nó tạo ra một phiên bản duy nhất của tệp cấu hình có thể được nhiều cuộc gọi truy cập đồng thời vì nó sẽ cung cấp dữ liệu cấu hình tĩnh được tải vào các đối tượng trong bộ nhớ. Ứng dụng chỉ đọc từ tệp cấu hình lần đầu tiên và sau đó từ lần gọi thứ hai trở đi, các ứng dụng khách đọc dữ liệu từ các đối tượng trong bộ nhớ.
  4. Bộ nhớ đệm : Chúng ta có thể sử dụng bộ đệm ẩn như một đối tượng singleton vì nó có thể có một điểm tham chiếu toàn cục và đối với tất cả các lệnh gọi trong tương lai tới đối tượng bộ đệm, ứng dụng khách sẽ sử dụng đối tượng trong bộ nhớ.

Điểm quan trọng

  • Các lớp Singleton chỉ có thể có một thể hiện và thể hiện đó phải có thể truy cập được trên toàn cầu.
  • java.lang.Runtime và java.awt.Desktop là 2 lớp singleton được cung cấp bởi JVM.
  • Design Pattern Singleton là một loại creational Design Pattern.
  • Các lớp bên ngoài nên được ngăn chặn để tạo thể hiện của lớp singleton.

Cài ứng dụng cafedev để dễ dàng cập nhật tin và học lập trình mọi lúc mọi nơi tại đây.

Tài liệu từ cafedev:

Nếu bạn thấy hay và hữu ích, bạn có thể tham gia các kênh sau của cafedev để nhận được nhiều hơn nữa:

Chào thân ái và quyết thắng!

Đăng ký kênh youtube để ủng hộ Cafedev nha các bạn, Thanks you!