Lecture 11 Singleton
Joseph Haugh
University of New Mexico
Free Recall
- Get out a sheet of paper or open a text editor
- For 2 minutes write down whatever comes to mind about the last class
- This could be topics you learned
- Questions you had
- Connections you made
Global State??
![]()
The Notion of a Singleton
- Sometimes we may need one instance of an object:
- Thread pools, caches, dialog boxes, logging objects, device drivers, etc.
- In many of these cases, instantiating more than one of such objects creates all kinds of problems
- incorrect program behavior
- resource overuse
- inconsistent results
Towards a Singleton
In Java, how do you create a single object?
new MyClass()
And if you call that a second time?
You get a second, distinct object
How could you prevent such instantiation?
public class MyClass {
private MyClass() {}
}
Who can use such a private constructor?
Only code within MyClass
The Next Step
How can you get access to code within MyClass if you can’t instantiate it?
What about like this?
public class MyClass {
public static MyClass getInstance() {
// ...
}
}
How would you call that?
MyClass.getInstance();
How would you fill out the implementation to make sure that only a single instance of MyClass is ever created?
The Classic Singleton
public class Singleton {
private static Singleton uniqueInstance;
// additional instance variables
private Singleton() {}
public static Singleton getInstance() {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
// additional methods
}
The Singleton Pattern
- The Singleton Pattern ensures a class has only one instance and provides a global point of access to that instance.
The Singleton Class Diagram
![]()
We have a problem. . .
- The Singleton pattern, as we have implemented it, is not thread safe
- When multiple threads invoke the
getInstance() method, multiple instances of the object may be created!
- Thread1 might execute
if (uniqueInstance == null) and see its true
- Thread2 then executes
if (uniqueInstance == null) and see its true
- Thread1 creates an instance
- Thread2 creates an instance
Possible solution
One solution is to use eager instantiation instead of lazy instantiation
public class Singleton {
private static Singleton uniqueInstance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return uniqueInstance;
}
}
We will need to return to this type of problem when we study concurrent programming!
Public Field Approach
We can also opt to just make the singleton instance a public static final field:
public class Singleton {
public static final Singleton INSTANCE = new Singleton();
private Singleton() {}
}
This is even simpler than having a static method
The only downside to this vs a static method is you cannot change your mind about being a Singleton!
- Since user will be relying on
INSTANCE as part of the API we cannot remove it
- Whereas, we could change
getInstance to return multiple instances
Is Anything Truly Private?
![]()
What I am about to show must be only utilized in the most dire circumstances
Reflection
- Reflection allows us to manipulate boundaries of the language we are normally not allowed to cross
- This includes the scoping rules enforced by
public, private, and protected
- Here is some code to break our old singleton:
// Get the constructor reflectively, or in other words at runtime
Constructor<SingletonPublicField> constructor =
SingletonPublicField.class.getDeclaredConstructor();
// Make it public
constructor.setAccessible(true);
// Get the supposed only instance
SingletonPublicField unique1 = SingletonPublicField.INSTANCE;
// Then create another one
SingletonPublicField unique2 = constructor.newInstance();
// Show they are not the same
System.out.println("unique1 != unique2 = " + (unique1 != unique2)); // true
Unbreakable Singleton
- Luckily, Java gives a way to avoid this attack entirely!
- We can use enums to create our singleton
- Recall, that enums in Java are implemented as classes with a limited number of instances (the members of the enum)
- Perfect for creating a singleton
Enum Singleton
public enum Singleton {
INSTANCE
}
- All the same advantages as the public field approach
- Robust to reflection
- Same downside of public field as well, you cannot change your mind
Some Questions
- What’s the difference between a Singleton and a class in which all of the methods and variables are static?
- Using the Singleton pattern instead allows for complex initialization (especially if that initialization involves other classes and objects)
- Without the Singleton pattern, you can still implement these things, but the result are common “order of initialization” bugs that are hard to pin down
- Why can’t you subclass a Singleton?
- You can’t extend a class with a private constructor
- All of the derived classes share the same static variable “instance”
When To Use a Singleton?
- Very few problems warrant the use of singletons If your problem has the following three properties then you MAY want to use singletons
- There can only be one object
- Object controls concurrent access to a shared resource (i.e. database)
- Access to the resource will be necessary in separate parts of the system
- Another good rule of thumb is if you are only sending data to a shared object and no data is coming back out then a singleton might be appropriate (i.e. logging)