Photo by Leslie Cross on Unsplash

Java Design Patterns: Singleton

Ricardo Romero Benitez

--

Let’s say you want to use a class several times since it usually has information that must be used multiple times and also be easily accessible.

One approach to the solution is creating a class instance in every method that you require it and using as much as you want

AwesomeConfig.java

public class AwesomeConfig {

private final String version;

public AwesomeConfig(final String version) {
this.version = version;
}

public String getVersion() {
return version;
}
}

Example method:

public class AmazingService {

public void amazingLogic() {
final AwesomeConfig awesomeConfig = new AwesomeConfig("1.0.0");

if ("1.0.0".equals(awesomeConfig.getVersion())) {
System.out.println("We need to update");
} else {
System.out.println("All good");
}
}

public void awesomeAlgorithm() {
final AwesomeConfig awesomeConfig = new AwesomeConfig("2.0.0");

if ("1.0.0".equals(awesomeConfig.getVersion())) {
System.out.println("This algorithm doesn't work here");
} else {
System.out.println("All good");
}
}
}

Of course, this brings us a lot of complexity and boilerplate code. Do we need to instance our version every time for a method? What happens if the version changes and we want to make it to different places?

You can refactor it to a class method like the following, but you are creating an object every time that it is required, creating a memory leak:

public class AmazingService {

public void amazingLogic() {
final AwesomeConfig awesomeConfig = getAwesomeConfig();

if ("1.0.0".equals(awesomeConfig.getVersion())) {
System.out.println("We need to update");
} else {
System.out.println("All good");
}
}

public void awesomeAlgorithm() {
final AwesomeConfig awesomeConfig = getAwesomeConfig();

if ("1.0.0".equals(awesomeConfig.getVersion())) {
System.out.println("This algorithm doesn't work here");
} else {
System.out.println("All good");
}
}

private AwesomeConfig getAwesomeConfig() {
return new AwesomeConfig("1.0.0");
}

}

Another way to avoid this memory leak is by creating a static class variable, it resolves the multiple object creation and it’s being accessible to the entire class:

public class AmazingService {

private final static AwesomeConfig awesomeConfig = new AwesomeConfig("1.0.0");

public void amazingLogic() {
if ("1.0.0".equals(awesomeConfig.getVersion())) {
System.out.println("We need to update");
} else {
System.out.println("All good");
}
}

public void awesomeAlgorithm() {
if ("1.0.0".equals(awesomeConfig.getVersion())) {
System.out.println("This algorithm doesn't work here");
} else {
System.out.println("All good");
}
}

}

The main problem with this approach is that is only accessible to the class that owns the variable and you need to create a static class variable every time that you need to access it in different classes, creating again, inconsistency and multiple objects for the same class.

Here comes the singleton pattern

One cut-edge solution is using the singleton pattern, changing our config class to having just one static instance, you would be able to use it around your project and just creating one instance of it. Like this:

AwesomeConfig.java

public class AwesomeConfig {

private static final AwesomeConfig instance = new AwesomeConfig();
private String version;

public static AwesomeConfig getInstance() {
return instance;
}

public String getVersion() {
return version;
}
}

And using it as the following in our service:

AmazingService.java

public class AmazingService {

public void amazingLogic() {
final AwesomeConfig config = AwesomeConfig.getInstance();
if ("1.0.0".equals(config.getVersion())) {
System.out.println("We need to update");
} else {
System.out.println("All good");
}
}

public void awesomeAlgorithm() {
final AwesomeConfig config = AwesomeConfig.getInstance();
if ("1.0.0".equals(config.getVersion())) {
System.out.println("This algorithm doesn't work here");
} else {
System.out.println("All good");
}
}

}

👇 Did you like the article? Buy me a coffee! 👇

👉 https://www.buymeacoffee.com/rrbapps 👈

--

--

Ricardo Romero Benitez
Ricardo Romero Benitez

No responses yet