Mô hình sáng tạo: Singleton

Dec 04 2022
Bài viết này thảo luận cách mẫu Singleton chỉ thực thi một phiên bản duy nhất của một lớp từng được sản xuất và tồn tại trong suốt vòng đời của một ứng dụng. Nó là gì? Singleton là một mẫu thiết kế được sử dụng để tạo thể hiện của lớp duy nhất.

Bài viết này thảo luận cách mẫu Singleton chỉ thực thi một phiên bản duy nhất của một lớp từng được sản xuất và tồn tại trong suốt vòng đời của một ứng dụng.

Nó là gì?

Singleton là một mẫu thiết kế được sử dụng để tạo thể hiện của lớp duy nhất. Mẫu Singleton thường được sử dụng khi có một số ví dụ chỉ tồn tại một thể hiện duy nhất của một lớp và ràng buộc được thực thi. Ví dụ: bộ đệm, nhóm luồng và sổ đăng ký chỉ nên có một phiên bản.

Đặt hàm tạo ở chế độ riêng tư để đảm bảo rằng chỉ có một đối tượng lớp được tạo. Bằng cách đó, chỉ các thành viên của lớp mới có thể truy cập hàm tạo riêng và không ai khác.

Trong thế giới thực, mẫu Singleton đảm bảo rằng chỉ tồn tại một thể hiện lớp duy nhất và cung cấp một điểm truy cập toàn cầu cho nó.

sơ đồ lớp

Sơ đồ lớp chỉ chứa một thực thể.

Độc thân

Thí dụ

Giả sử chúng ta muốn lập mô hình chiếc máy bay chính thức của Tổng thống Mỹ có tên là Lực lượng Không quân Một trong phần mềm của mình. Lớp Singleton là cách biểu diễn phù hợp nhất cho một thực thể chỉ có một thể hiện.

Đây là mã cho lớp singleton của chúng tôi:

Đa luồng và Singleton

Mã này hoạt động miễn là ứng dụng là một luồng. Tuy nhiên, nếu nhiều luồng truy cập vào lớp này, có khả năng các đối tượng khác nhau sẽ được tạo.

Ví dụ:

  • Chủ đề A gọi phương thức getInstancevà tìm thấy giá onlyInstancetrị rỗng; tuy nhiên, trước khi nó có thể tạo một thể hiện, nó đã tắt ngữ cảnh.
  • Bây giờ luồng B xuất hiện và gọi getInstance, trả về AirforceOneđối tượng.
  • Nếu chủ đề A được lên lịch lại, trò nghịch ngợm bắt đầu. Chủ đề đã vượt qua kiểm tra điều kiện if-null và sẽ tiếp tục tạo một AirforceOneđối tượng mới và gán nó cho onlyInstance. Bây giờ có hai AirforceOneđối tượng khác nhau ngoài tự nhiên, một đối tượng có luồng A và một đối tượng có luồng B.
  • Bằng cách thêm synchronizedvào getInstance()phương thức, bạn có thể đạt được sự an toàn của luồng.
  • Một tùy chọn khác là khởi tạo thể hiện tĩnh, đảm bảo rằng nó an toàn cho luồng.

Khóa kiểm tra hai lần

Có hai vấn đề quan trọng với các cách tiếp cận được mô tả ở trên: đồng bộ hóa tốn kém và khởi tạo tĩnh tạo ra đối tượng ngay cả khi nó không được sử dụng trong một ứng dụng cụ thể. Nếu việc tạo đối tượng tốn kém, thì việc khởi tạo tĩnh có thể khiến chúng tôi mất hiệu năng.

Giải pháp trên đánh dấu trường hợp singleton dễ bay hơi. Tuy nhiên, việc triển khai phương pháp của JVM này volatilesẽ không hoạt động chính xác đối với khóa được kiểm tra hai lần và bạn sẽ cần một cách tiếp cận khác để tạo các đĩa đơn của mình.

Thành ngữ khóa được kiểm tra hai lần hiện được coi là một phản mẫu và tiện ích của nó chủ yếu đã biến mất khi thời gian khởi động JVM tăng lên.

Những ví dụ khác

Java API cung cấp cho chúng ta các singletons sau:

java.lang.Runtime

java.awt.Desktop

Hãy cẩn thận

Bạn có thể phân lớp một lớp đơn bằng cách bảo vệ hàm tạo thay vì riêng tư. Tuy nhiên, có những lựa chọn tốt hơn điều này trong mọi trường hợp. Trong những tình huống này, các nhà phát triển có thể tạo một sổ đăng ký các singletons cho tất cả các lớp con. Phương thức getInstance có thể nhận tham số hoặc sử dụng biến môi trường để trả về đối tượng đơn mong muốn. Cơ quan đăng ký duy trì ánh xạ tên chuỗi tới các đối tượng đơn lẻ.

Các bài viết khác trong sê-ri Mẫu sáng tạo