Skip to main content

Command Palette

Search for a command to run...

Hướng dẫn Singleton Pattern trong Java

Published
5 min readView as Markdown

1. Giới thiệu Singleton Pattern

Singleton Pattern là một mẫu thiết kế thuộc nhóm Creational Patterns, được sử dụng để đảm bảo rằng một lớp chỉ có một instance duy nhất và cung cấp một điểm truy cập toàn cục cho instance đó. Mẫu thiết kế này hữu ích khi chúng ta cần kiểm soát việc truy cập và tạo đối tượng, đảm bảo rằng chỉ một instance duy nhất của lớp được tạo ra trong toàn bộ chương trình.

2. Các trường hợp ứng dụng Singleton Pattern

  • Quản lý kết nối cơ sở dữ liệu: Một ứng dụng chỉ cần một instance của lớp quản lý kết nối để tiết kiệm tài nguyên và quản lý kết nối hiệu quả.

  • Cấu hình hệ thống: Các thông số cấu hình thường cần được truy cập từ nhiều nơi trong ứng dụng, nhưng chỉ cần một instance của lớp cấu hình để duy trì nhất quán.

  • Loggers: Ghi log thường cần được quản lý bởi một instance duy nhất để tránh ghi log từ nhiều nguồn gây ra xung đột.

3. Các phương pháp triển khai Singleton Pattern

Có nhiều cách triển khai Singleton Pattern, mỗi cách có ưu và nhược điểm riêng. Dưới đây là một số cách triển khai phổ biến:

3.1. Eager Initialization (Khởi tạo sớm)

public class EagerSingleton {
    private static final EagerSingleton INSTANCE = new EagerSingleton();

    private EagerSingleton() {
        // Private constructor to prevent instantiation
    }

    public static EagerSingleton getInstance() {
        return INSTANCE;
    }
}
  • Ưu điểm: Đơn giản, dễ hiểu.

  • Nhược điểm: Instance được tạo ngay khi lớp được tải, không phù hợp nếu instance tốn nhiều tài nguyên và không cần thiết ngay lập tức.

3.2. Lazy Initialization (Khởi tạo lười)

public class LazySingleton {
    private static LazySingleton instance;

    private LazySingleton() {
        // Private constructor to prevent instantiation
    }

    public static LazySingleton getInstance() {
        if (instance == null) {
            instance = new LazySingleton();
        }
        return instance;
    }
}
  • Ưu điểm: Instance chỉ được tạo khi cần thiết.

  • Nhược điểm: Không an toàn trong môi trường đa luồng.

3.3. Thread-Safe Singleton (Singleton an toàn trong môi trường đa luồng)

public class ThreadSafeSingleton {
    private static ThreadSafeSingleton instance;

    private ThreadSafeSingleton() {
        // Private constructor to prevent instantiation
    }

    public static synchronized ThreadSafeSingleton getInstance() {
        if (instance == null) {
            instance = new ThreadSafeSingleton();
        }
        return instance;
    }
}
  • Ưu điểm: An toàn trong môi trường đa luồng.

  • Nhược điểm: Hiệu năng kém hơn do sử dụng synchronized.

3.4. Double-Checked Locking (Khóa kép)

public class DoubleCheckedLockingSingleton {
    private static volatile DoubleCheckedLockingSingleton instance;

    private DoubleCheckedLockingSingleton() {
        // Private constructor to prevent instantiation
    }

    public static DoubleCheckedLockingSingleton getInstance() {
        if (instance == null) {
            synchronized (DoubleCheckedLockingSingleton.class) {
                if (instance == null) {
                    instance = new DoubleCheckedLockingSingleton();
                }
            }
        }
        return instance;
    }
}
  • Ưu điểm: Cải thiện hiệu năng bằng cách giảm thiểu việc sử dụng synchronized.

  • Nhược điểm: Cần sự hiểu biết sâu về volatile và synchronized.

3.5. Bill Pugh Singleton (Sử dụng inner static helper class)

public class BillPughSingleton {
    private BillPughSingleton() {
        // Private constructor to prevent instantiation
    }

    private static class SingletonHelper {
        private static final BillPughSingleton INSTANCE = new BillPughSingleton();
    }

    public static BillPughSingleton getInstance() {
        return SingletonHelper.INSTANCE;
    }
}
  • Ưu điểm: Đơn giản, an toàn trong môi trường đa luồng mà không cần synchronized.

  • Nhược điểm: Khá khó hiểu đối với người mới học.

4. Ví dụ minh họa Singleton Pattern

4.1. Quản lý kết nối cơ sở dữ liệu

public class DatabaseConnection {
    private static volatile DatabaseConnection instance;
    private Connection connection;

    private DatabaseConnection() {
        try {
            // Giả sử đang sử dụng JDBC để kết nối cơ sở dữ liệu
            Class.forName("com.mysql.cj.jdbc.Driver");
            this.connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "user", "password");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static DatabaseConnection getInstance() {
        if (instance == null) {
            synchronized (DatabaseConnection.class) {
                if (instance == null) {
                    instance = new DatabaseConnection();
                }
            }
        }
        return instance;
    }

    public Connection getConnection() {
        return connection;
    }
}

Trong ví dụ này, lớp DatabaseConnection đảm bảo rằng chỉ có một instance duy nhất của lớp được tạo ra, và instance này quản lý kết nối tới cơ sở dữ liệu.

5. Phân tích các trường hợp ứng dụng Singleton Pattern

5.1. Quản lý kết nối cơ sở dữ liệu

  • Ưu điểm: Tiết kiệm tài nguyên bằng cách chỉ tạo một kết nối duy nhất.

  • Nhược điểm: Nếu kết nối gặp sự cố, toàn bộ ứng dụng có thể bị ảnh hưởng.

5.2. Cấu hình hệ thống

  • Ưu điểm: Dễ dàng quản lý và truy cập các thông số cấu hình từ bất kỳ đâu trong ứng dụng.

  • Nhược điểm: Cần đảm bảo rằng cấu hình được tải một cách an toàn và nhất quán.

5.3. Loggers

  • Ưu điểm: Tránh xung đột khi ghi log từ nhiều nguồn khác nhau.

  • Nhược điểm: Cần quản lý truy cập đồng thời một cách hiệu quả.

6. Kết luận

Singleton Pattern là một mẫu thiết kế mạnh mẽ và hữu ích trong nhiều trường hợp khác nhau. Tuy nhiên, cần cân nhắc và triển khai đúng cách để tránh các vấn đề về hiệu năng và an toàn trong môi trường đa luồng. Hiểu rõ các phương pháp triển khai khác nhau sẽ giúp lập trình viên chọn lựa giải pháp phù hợp cho từng trường hợp cụ thể trong các dự án Java Spring Boot.

More from this blog

hoangkim

366 posts