Patterns Revisited Singleton
3 minute read
A SIMPLE CREATIONAL PATTERN
Globals are bad. Data should be encapsulated and only available when needed. These are some of the first things you learn when you start to program. If there are multiple actors that can write to shared data, side affects can occur. However there are times when having a single instance of data is required. In the singleton pattern there is only one instance of a class, which you cannot explicitly create.
Data that doesn’t change often, but is needed throughout your application. Some Examples:
- Passwords loaded from a 3rd party password vault at application startup.
- Configuration data used by multiple parts of an application.
- A common logger that gets used over and over.
HOW TO CREATE A SINGLETON
The singleton pattern is one of the simplest patterns. To create a singleton you only need one class. The examples below show the class being initialized with data that cannot change. In the examples, I hardcoded a URL for simplicity, however in practice data could be read from a file, network location or a service.
Java
public class Single
{
private static final Single instance = new Single();
private String url;
private Single()
{
url = "https://www.leantechniques.com";
}
public static Single getInstance(){
return instance;
}
public String getUrl(){
return url;
}
}
//Usage
private Single single = Single.getInstance();
private String url = single.url;
Kotlin
object Single{
val url = "https://www.leantechniques.com"
}
//Usage
val string = Single.url
Swift
class Single {
let url = "https://www.leantechniques.com"
static let sharedInstance = Single()
private init() {
}
}
//Usage
let single = Single.sharedInstance
let url = single.url
GOTCHAS USING A SINGLETON
If you create a singleton that allows the data to change after instantiation, you have to be aware of side effects and thread safety. This is also dependent on the language that you choose. Kotlin objects are thread safe, Java classes are not. The example below is of a Singleton written in Java that is thread safe.
public class Single
{
private static Single instance;
private String url;
private Single() {
url = "https://www.leantechniques.com";
}
synchronized public static Single getInstance(){
if(instance!=null) {
return instance;
}else{
return new Single();
}
}
public void setUrl(String url){
this.url = url;
}
public String getUrl(){
return url;
}
}
TESTING A CLASS THAT USES MOCKS.
Another challenge you might come across is how to mock a singleton. For example using Mockito to test a Java program you can’t mock static methods. You might need to pull in a library such as PowerMock. If you are writing code in Kotlin you can use a library such as Mockk.
ON TO THE FACADE PATTERN…
In the next rant, I am going to explore a the facade pattern. The facade is a structural pattern as opposed to a creational pattern.