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)