0
0
Lập trình
Flame Kris
Flame Krisbacodekiller

Tìm hiểu về Design Pattern - Singleton trong lập trình Java

Đăng vào 4 ngày trước

• 4 phút đọc

Chào mừng bạn đến với series Design Pattern trong lập trình hướng đối tượng

Chào mừng anh em trở lại với series Design Pattern thực chiến trong lập trình hướng đối tượng. Singleton là một trong những design pattern quan trọng nhất thuộc nhóm Creational Pattern. Mục tiêu chính của nó là đảm bảo rằng một class chỉ có duy nhất một instance trong toàn bộ vòng đời của chương trình và cung cấp một điểm truy cập toàn cục đến instance này. Điều này rất hữu ích trong nhiều tình huống đòi hỏi sự nhất quán về trạng thái của đối tượng hoặc tài nguyên, chẳng hạn như khi làm việc với database connection hay loggers. Trong bài viết này, chúng ta sẽ cùng tìm hiểu khái niệm, cấu trúc và cách triển khai Singleton trong ngôn ngữ lập trình Java.

I. Khái niệm và cấu trúc

1. Ý định (Intent)

Trích từ cuốn Design patterns Elements of Reusable Object-Oriented Software:

Đảm bảo một class chỉ có một instance, và cung cấp một điểm truy cập toàn cục đến nó.

GoF

Nhóm: Creational pattern

Pattern này có hai mục tiêu chính:

  1. Đảm bảo một class chỉ có một instance duy nhất, ngăn chặn việc khởi tạo nhiều instance của một class.
  2. Cung cấp một điểm truy cập toàn cục (global access point): sử dụng một static method cho phép các thành phần khác truy cập vào instance duy nhất này.

2. Cấu trúc tổng quát

Cấu trúc của Singleton rất đơn giản, chỉ có một class:

Singleton: class chứa ít nhất ba thành phần chính:

  1. Private static instance private static Instance
  2. Private constructor private Singleton()
  3. Public static method getInstance() cung cấp điểm truy cập tới instance cho các thành phần khác.

3. Ứng dụng

Singleton được sử dụng khi cần quản lý tài nguyên hệ thống một cách nhất quán. Một số ví dụ thực tế có thể bao gồm quản lý database connection, loggers hoặc các cấu hình hệ thống phức tạp nhưng đòi hỏi sự nhất quán trên toàn bộ hệ thống.

II. Thực hành triển khai trong Java

1. Naive implementation

Đúng như định nghĩa trên, chúng ta có:

  1. Private static instance
  2. Private constructor
  3. Public static method getInstance()

NaiveSingleton

java Copy
public class NaiveSingleton {
  private static NaiveSingleton instance;
  private NaiveSingleton() {}

  public static NaiveSingleton getInstance() {
    if(Objects.isNull(instance)) {
      instance = new NaiveSingleton();
    }
    return instance;
  }
}

2. Triển khai an toàn với đa luồng (Thread-safe implementation)

Vấn đề của implementation đầu tiên là nó sẽ gây ra lỗi khi có nhiều thread cùng tham gia vào quá trình tạo instance. Hãy tưởng tượng trường hợp có hai thread cùng gọi phương thức getInstance() khi instance chưa được khởi tạo. Lúc này, cả hai sẽ cùng tạo ra hai instance, làm phá vỡ quy tắc chỉ cho phép một instance duy nhất.

Để giải quyết vấn đề này, có những cách sau:

  • Static Initialization: Khởi tạo instance ngay tại câu lệnh định nghĩa instance. Điểm yếu của phương pháp này là nó không hỗ trợ lazy load.
java Copy
private static Singleton instance = new Singleton();
  • Synchronized Method: Phương pháp này gặp vấn đề về performance vì các thread phải chờ khóa được giải phóng mỗi khi gọi phương thức getInstance().
java Copy
public static synchronized Singleton getInstance() {
  if(Objects.isNull(instance)) {
    instance = new Singleton();
  }
  return instance;
}
  • Double-Checked Locking: Phương pháp này vừa hỗ trợ lazy load và cũng cải thiện đáng kể hiệu suất.
java Copy
public class ThreadSafeSingleton {
    private static volatile ThreadSafeSingleton instance;
    private ThreadSafeSingleton() {}

    public static ThreadSafeSingleton getInstance() {
        ThreadSafeSingleton result = instance;
        if(Objects.nonNull(result)) {
            return result;
        }
        synchronized (ThreadSafeSingleton.class) {
            if (Objects.isNull(instance)) {
                instance = new ThreadSafeSingleton();
            }
            return instance;
        }
    }
}

Để tìm hiểu đầy đủ, bạn có thể tham khảo mã nguồn tại link: design-pattern-made-easy/singleton.

III. Lời kết

Singleton là một pattern đơn giản nhưng mạnh mẽ, giúp tối ưu hóa việc quản lý tài nguyên và đảm bảo tính nhất quán trong hệ thống. Từ cách tiếp cận naive đến các giải pháp tối ưu như Thread-safe Singleton và Double-checked locking, chúng ta có thể lựa chọn phương pháp phù hợp với yêu cầu cụ thể của từng ứng dụng. Sử dụng Singleton không chỉ cải thiện hiệu suất mà còn giúp duy trì một kiến trúc rõ ràng và hiệu quả. Hẹn gặp lại bạn trong các bài viết tiếp theo!

IV. Tài liệu tham khảo

  1. Refactoring.guru
  2. Head First Design Pattern - O'Reilly
  3. Design Patterns: Elements of Reusable Object-Oriented Software - GoF

Nếu bạn thấy bài viết hữu ích, hãy click upvote để ủng hộ bài viết này. Nếu bạn có bất kỳ câu hỏi hay ý kiến nào, hãy để lại comment để chúng ta cùng trao đổi nhé! Bạn cũng có thể tham khảo các bài viết khác của tôi tại blog cá nhân hoặc kết nối với tôi qua LinkedIn.
source: viblo

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào