Menu
Coddy logo textTech

Singleton Pattern

Part of the Object Oriented Programming section of Coddy's Java journey — lesson 65 of 87.

The Singleton Pattern is a creational design pattern that ensures a class has only one instance throughout your application, while providing a global access point to that instance. This is useful for resources that should be shared, like configuration managers, connection pools, or logging services.

The pattern works by making the constructor private, preventing direct instantiation. Instead, a static method controls access to the single instance:

public class DatabaseConnection {
    private static DatabaseConnection instance;
    
    // Private constructor prevents direct instantiation
    private DatabaseConnection() {
        System.out.println("Connection created");
    }
    
    // Global access point
    public static DatabaseConnection getInstance() {
        if (instance == null) {
            instance = new DatabaseConnection();
        }
        return instance;
    }
    
    public void query(String sql) {
        System.out.println("Executing: " + sql);
    }
}

Every call to getInstance() returns the same object. The instance is created only when first requested—this is called lazy initialization:

DatabaseConnection db1 = DatabaseConnection.getInstance();
DatabaseConnection db2 = DatabaseConnection.getInstance();

System.out.println(db1 == db2);  // true - same instance

The key components of a Singleton are: a private static field holding the instance, a private constructor, and a public static method that returns the instance. This combination guarantees that no matter how many times you request the object, you always get the same one.

challenge icon

Challenge

Easy

Let's build a configuration manager for an application using the Singleton Pattern! Your configuration manager will ensure that all parts of your application share the same settings, no matter how many times they request access to it.

You'll organize your code across two files:

  • AppConfig.java: Create a Singleton class that manages application configuration settings. Your AppConfig should have:

    A private static field to hold the single instance.

    A private String field called appName and a private int field called maxUsers.

    A private constructor that initializes appName to "MyApplication" and maxUsers to 100, then prints AppConfig initialized.

    A public static getInstance() method that creates the instance only if it doesn't exist yet (lazy initialization), then returns it.

    A setAppName(String name) method that updates the app name.

    A setMaxUsers(int max) method that updates the max users.

    A displaySettings() method that prints App: [appName], Max Users: [maxUsers].

  • Main.java: Demonstrate that your Singleton works correctly! You'll receive two inputs: a new app name (String) and a new max users value (integer).

    First, get an instance of AppConfig and store it in a variable called config1. Call displaySettings() to show the default values.

    Then update the settings using your input values by calling setAppName and setMaxUsers on config1.

    Get another instance and store it in config2. Call displaySettings() on config2 to prove it reflects the changes made through config1.

    Finally, print whether both references point to the same object: Same instance: [true/false] by comparing config1 == config2.

You will receive two inputs in order: the new app name (String) and the new max users (integer).

This challenge demonstrates the core benefit of the Singleton Pattern: no matter how many times you request the configuration, you always get the same instance with the same shared state!

Cheat sheet

The Singleton Pattern ensures a class has only one instance throughout the application, providing a global access point to that instance.

Key Components:

  • A private static field holding the single instance
  • A private constructor to prevent direct instantiation
  • A public static method that returns the instance

Basic Implementation:

public class DatabaseConnection {
    private static DatabaseConnection instance;
    
    // Private constructor prevents direct instantiation
    private DatabaseConnection() {
        System.out.println("Connection created");
    }
    
    // Global access point
    public static DatabaseConnection getInstance() {
        if (instance == null) {
            instance = new DatabaseConnection();
        }
        return instance;
    }
    
    public void query(String sql) {
        System.out.println("Executing: " + sql);
    }
}

Usage:

DatabaseConnection db1 = DatabaseConnection.getInstance();
DatabaseConnection db2 = DatabaseConnection.getInstance();

System.out.println(db1 == db2);  // true - same instance

The instance is created only when first requested—this is called lazy initialization. Every call to getInstance() returns the same object, ensuring shared state across the application.

Try it yourself

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // Read inputs
        String newAppName = scanner.nextLine();
        int newMaxUsers = scanner.nextInt();
        
        // TODO: Get first instance of AppConfig and store in config1
        
        // TODO: Call displaySettings() on config1 to show default values
        
        // TODO: Update settings using setAppName and setMaxUsers on config1
        
        // TODO: Get another instance and store in config2
        
        // TODO: Call displaySettings() on config2 to prove changes are shared
        
        // TODO: Print whether both references point to same object:
        // "Same instance: [true/false]" using config1 == config2
    }
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming