Singletons are classes which can have no more than one object. They're most useful for storing global state across a system.
Some situations where one might use a singleton include:
Singletons are contentious these days. Many people believe they should be avoided, or at least be used less often than they generally are.
Even so, implementing a singleton is an interesting coding challenge.
Suppose we wanted a singleton called InstallationDetails that stored some information, including the licenseNumber. How would we implement this?
We have several options. The first is lazy: have the class get or create its instance just in time, as it's requested:
public final class InstallationDetails {
private static InstallationDetails INSTANCE = null;
private long licenseNumber;
public long getLicenseNumber() {
return licenseNumber;
}
// by making the constructor private, we prevent instantiation
private InstallationDetails() {
this.licenseNumber = ... ;
}
public static InstallationDetails getInstance() {
if(INSTANCE == null) {
INSTANCE = new InstallationDetails();
}
return INSTANCE;
}
}
Java
To make this thread-safe:
public final class InstallationDetails {
private static volatile InstallationDetails INSTANCE = null;
private long licenseNumber;
public long getLicenseNumber() {
return licenseNumber;
}
// by making the constructor private, we prevent instantiation
private InstallationDetails() {
this.licenseNumber = ... ;
}
public static InstallationDetails getInstance() {
if(INSTANCE == null) {
synchronized (InstallationDetails.class) {
if(INSTANCE == null) {
INSTANCE = new InstallationDetails();
}
}
}
return INSTANCE;
}
}
Java
Another is to eagerly have the class instantiate its singleton object even before one is requested:
public final class InstallationDetails {
private static final InstallationDetails INSTANCE = new InstallationDetails();
private long licenseNumber;
public long getLicenseNumber() {
return licenseNumber;
}
// by making the constructor private, we prevent instantiation
private InstallationDetails() {
this.licenseNumber = ... ;
}
public static InstallationDetails getInstance() {
return INSTANCE;
}
}
Java
There's also the initialization-on-demand way:
public final class InstallationDetails {
private long licenseNumber;
public long getLicenseNumber() {
return licenseNumber;
}
// by making the constructor private, we prevent instantiation
private InstallationDetails() {
this.licenseNumber = ... ;
}
private static class InstallationDetailsHolder {
private static final InstallationDetails INSTANCE = new InstallationDetails();
}
public static InstallationDetails getInstance() {
return InstallationDetailsHolder.INSTANCE;
}
}
Java