Design pattern singleton là gì
Singleton Pattern là một pattern cực kỳ cơ bản và hiệu quả mà chắc chắn rất nhiều lập trình viên trong chúng ta vẫn sử dụng thường xuyên nên mình sẽ chỉ nói qua về khái niệm thôi. Show
Mục đích của Singleton PatternMột class thuộc dạng Singleton có nghĩa là: nó chỉ có một instance duy nhất, bất kỳ ở đâu đều có thể truy cập tới instance của class singleton đó. Singleton pattern là gì? Singleton pattern là gì?Singleton pattern là 1 trong 5 design pattern thuộc nhóm Creational Design Pattern.Singleton pattern đảm bảo chỉ duy nhất một thể hiện (instance) được tạo ra và bạn có thể truy xuất được thể hiện duy nhất đó mọi lúc mọi nơi trong chương trình. Singleton có 1 instance duy nhất và được các class khác gọi tới Singleton pattern dùng để làm gì?Việc sử dụng Singleton pattern sẽ giúp chúng ta đảm bảo những điều sau đây:
Các nguyên tắc cơ bản để implement Singleton patternChúng ta có rất nhiều cách để implement Singleton pattern. Nhưng dù cho việc implement bằng cách nào đi nữa cũng cần dựa vào những nguyên tắc dưới cơ bản dưới đây:
9 cách để implement Singleton pattern phổ biến nhấtDựa trên những nguyên tắc thiết kế Singleton trên, chúng ta có 9 cách implement Singleton pattern sau: Eager initialization (Khởi tạo sớm)Singleton Class sẽ được khởi tạo ngay khi chương trình chạy. Đây là cách dễ dàng nhất, đơn giản nhất nhưng nó có một nhược điểm: mặc dù instance đã được khởi tạo nhưng có thể sẽ không dùng tới. Ví dụ: Eager initialization dễ cài đặt nhưng nó dễ dàng bị phá vỡ bởi Reflection Static block initializationChúng ta làm tương tự như Eager initialization chỉ khác ở phần static block cung cấp thêm lựa chọn cho việc handle exception hay các xử lý khác. Ví dụ: Lazy InitializationLazy Initialization ra đời đã giúp khắc phục nhược điểm của Eager Initialization. Chỉ khi nào được gọi, instance mới được khởi tạo. Nó giúp bạn không phải khởi tạo class khi bạn không cần. Tuy nhiên, đối với thao tác create instance quá chậm thì người dùng có thể phải chờ lâu cho lần sử dụng đầu tiên. Lazy Initialization cũng chỉ hoạt động tốt với trường hợp chương trình của chúng ta là đơn luồng (single-thread). Nếu tại một thời điểm mà có hai luồng (multi-thread) cùng gọi đến phương thức getInstance() thì sẽ xảy ra trường hợp 2 thực thể (instance) sẽ được khởi tạo cùng một lúc.Để khắc phục nhược điểm trên, phương pháp Thread Safe Singleton đã được ra đời. Thread Safe InitializationThread Safe Initialization khắc phục nhược điểm của Lazy Initialization bằng cách gọi phương thức synchronized của hàm getInstance(). Như vậy sẽ đảm bảo cho việc tại một thời điểm chỉ có một luồng (single-thread) được phép truy cập vào hàm getInstance() và chỉ có duy nhất 1 instance của class. Tuy nhiên, phương pháp này sẽ làm chương trình chạy chậm và tốn hiệu năng. Bất kỳ một Thread nào gọi đến đều phải chờ nếu có một Thread khác đang sử dụng. Có những tác vụ xử lý trước và sau khi tạo instance không cần thiết phải block. Do vậy chúng ta cần có một phương pháp ưu việt hơn, đó chính là Double Check Locking Singleton. Ví dụ của Thread Safe Initialization Double Check Locking SingletonĐể implement Singleton pattern theo cách này, chúng ta sẽ kiểm tra sự tồn tại instance của class, với sự hỗ trợ của đồng bộ hóa, hai lần trước khi khởi tạo. Bạn cần khai báo volatile cho instance nhằm tránh class làm việc không chính xác do quá trình tối ưu hóa của trình biên dịch Ví dụ về Double Check Locking Singleton Bill Pugh Singleton ImplementationBill Pugh Singleton implementation tạo ra static nested class với chức năng 1 Helper khi muốn tách biệt chức năng cho 1 class function rõ ràng hơn. Đây là cách thường được sử dụng nhiều và có hiệu suất tốt. Ví dụ về Bill Pugh Singleton Implementation Trong khi Singleton được tải vào bộ nhớ thì Singleton Helper vẫn chưa được tải vào. Singleton Helper chỉ được tải vào khi phương thức getInstance() được gọi. Phương pháp này giúp tránh được lỗi cơ chế khởi tạo thực thể của Singleton trong Multi-Thread, performance cao. Do đã tách biệt được quá trình xử lý. Cũng chính vì vậy mà phương pháp này được người lập trình đánh giá là cách triển khai Singleton nhanh và hiệu quả nhất. Reflection Singleton PatternReflection có thể được dùng để phá vỡ Pattern của Eager Initialization và Bill Pugh Singleton như ví dụ dưới đây: Ví dụ về Reflection Singleton Pattern Khi đó Output của chương trình là: Enum SingletonKhi dùng Enum các params chỉ được khởi tạo 1 lần duy nhất. Đây cũng là cách để bạn tạo ra Singleton instance. Ví dụ: Lưu ý 2 điều sau đây khi dùng Enum Singleton:
Serialization and SingletonTrong các hệ thống phân tán (distributed system), đôi lúc chúng ta cần implement interface Serializable trong lớp Singleton để chúng ta có thể lưu trữ trạng thái của nó trong file hệ thống và truy xuất lại nó sau. Ví dụ: Đoạn code test quá trình Serialize/ Deserialize: Output của chương trình là: Như ở ví dụ trên, Deserialize đối tượng của Serialized Singleton khác với đối tượng gốc. Nhưng nó sẽ không xảy ra khi bạn dùng phương pháp Enum. Trên thực tế, vẫn có cách khắc phục khi sử dụng class Serialized Singleton là implement một phương thức readResolve(). Nhưng khi chúng ta thật sự gặp vấn đề và cần sử dụng Serialize/ Deserialize, thì nên sử dụng Enum sẽ đơn giản hơn. Một số ứng dụng của Singleton PatternChúng ta có thể thấy Singleton Pattern được ứng dụng trong các trường hợp:
Logger: Các class Singleton được ứng dụng trong các tệp nhật ký. Các tệp nhật ký được tạo bởi đối tượng class trình ghi nhật ký. Ví dụ, 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ể sẽ tạo nhiều bản sao của lớp này và có thể gây ra lỗi trong quá trình truy cập cùng lúc vào cùng một file trình ghi nhật ký. Chúng ta có thể 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. Tệp cấu hình: Singleton pattern rất phù hợp để ứng dụng vào tệp cấu hình vì nó ngăn cả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.
Trên đây là một số những ứng dụng phổ biến của Singleton pattern. Ngoài ra, Singleton pattern còn có rất nhiều ứng dụng khác. Qua bài viết trên, chúng tôi hy vọng đã giúp bạn hiểu hơn về Singleton pattern là gì? Chức năng, các cách thực thi và ứng dụng của Singleton pattern trong thực tế. Từ đó bạn có thể áp dụng Singleton một cách hiệu quả nhất trong công việc của mình nhé! Mẫu thiết kế Singleton dùng để làm gì?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.
Sử dụng Singleton pattern khi nào?Sử dụng Singleton Pattern khi nào?. Vì class dùng Singleton chỉ tồn tại 1 Instance nên nó thường được dùng cho các trường hợp giải quyết những bài toán cần truy cập vào các ứng dụng như: Shared resource, Logger, Configuration, Thread pool,... Sử dụng trong một số class của core java như: java. lang. Runtime, java. awt.. Tại sao nên dùng Singleton?Việc sử dụng Singleton pattern sẽ giúp chúng ta đảm bảo những điều sau đây: Đảm bảo chỉ có 1 thể hiện (instance) của lớp (class). Giúp quản lý việc truy cập tốt hơn vì chỉ có 1 thể hiện (instance) duy nhất. Quản lý được số lượng thể hiện (instance) của một lớp (class) trong một giới hạn chỉ định.
Singleton sét là gì?Trong toán học, 1 singleton còn được gọi là một tập đơn vị, là một tập hợp có đúng một phần tử. Ví dụ: tập {null} là 1 singleton. Design Pattern này được dùng khi ta muốn đảm bảo chỉ có duy nhất một object được sinh ra trong toàn hệ thống. Tức là chúng ta giới hạn việc khởi tạo một class đối với một object.
|