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 instanceThe 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
EasyLet'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. YourAppConfigshould have:A private static field to hold the single instance.
A private String field called
appNameand a private int field calledmaxUsers.A private constructor that initializes
appNameto"MyApplication"andmaxUsersto100, then printsAppConfig 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 printsApp: [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
AppConfigand store it in a variable calledconfig1. CalldisplaySettings()to show the default values.Then update the settings using your input values by calling
setAppNameandsetMaxUsersonconfig1.Get another instance and store it in
config2. CalldisplaySettings()onconfig2to prove it reflects the changes made throughconfig1.Finally, print whether both references point to the same object:
Same instance: [true/false]by comparingconfig1 == 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 staticfield holding the single instance - A
privateconstructor to prevent direct instantiation - A
public staticmethod 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 instanceThe 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
}
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesIntroduction to OOPClasses vs ObjectsThe this KeywordMethodsFields (Attributes)Constructor MethodConstructor OverloadingRecap - Simple Calculator4Inheritance
Basic Inheritance (extends)The super KeywordMethod Overriding (@Override)Constructor ChainingThe Object ClassSingle & Multilevel InheritWhy No Multi Class InheritRecap - Employee Hierarchy7Special Methods & Object Class
toString() Methodequals() and hashCode()clone() MethodcompareTo() and ComparableComparator InterfaceRecap - Custom Sorting2Access Modifiers & Encapsulate
Access Levels OverviewGetter and Setter MethodsInformation HidingThe final KeywordRecap - Bank Account Manager5Polymorphism
Method Overloading BasicsMethod Overriding (Run-Time)Upcasting and DowncastingThe instanceof OperatorAbstract Classes and MethodsRecap - Shape Calculator8Advanced OOP Concepts
Composition vs InheritanceAggregation vs CompositionInner Nested & Anonymous ClassEnums and Enum MethodsRecords (Java 16+)Sealed Classes (Java 17+)11Design Patterns Part 1
Intro to Design PatternsSingleton PatternFactory PatternBuilder PatternObserver PatternStrategy Pattern3Class Props & Static Member
Instance vs Static VariablesStatic MethodsStatic BlocksConstants (static final)Recap - Counter & Utility6Interfaces & Abstract Classes
Introduction to InterfacesImplementing InterfacesMulti Interface ImplemenDefault & Static in InterfaceAbstract Classes vs InterfacesFunctional InterfacesRecap - Payment System