How to Lazy Load Without Using if Statements
What is Lazy Loading?
Lazy loading is when you put off loading something until it is needed. This is usually done inside of a method. The method that is lazy loading a value has to be wrapped in an if statement to check if the value is loaded or not. If it isn't loaded, it will then load the value and return it. If it is loaded, it will simply return the value. For example:
// Java code
public final class UserService {
private User admin = null;
public User admin() {
if (admin == null) {
admin = userDao.find("admin");
}
return admin;
}
}
Lazy loading also prevents you from being able to make the lazy loaded variable a constant.
Logicless Lazy Loading
Some programming languages such as Scala, have lazy loading built into the language. An example of using Scala's lazy keyword is the following:
// Scala code
lazy val admin = {
userDao.find("admin")
}
This Scala code will only run the function once and then cache the result. In Scala, you will work with the value the same whether it has been loaded or not.
This pattern can be implemented in other languages, but not always as simple as this.
Implementing in Java
In Java, it isn't as simple, but it can get pretty close. Using the following class, you can get the same behavior.
// Java code
public final class Lazy<T> {
private final Supplier<T> supplier;
private T value = null;
private Lazy(final Supplier<T> supplier) {
this.supplier = supplier;
}
public static <T> Lazy<T> load(final Supplier<T> supplier) {
return new Lazy<>(supplier);
}
public T get() {
if (value == null) {
value = supplier.get();
}
return value.get();
}
}
In Java, a Supplier is a zero parameter function that returns something. The if statement to determine if it needs to be loaded is written in the get() method and shared anytime you need to lazy load. This class allows you to gain the same behavior shown in the Scala example. This also eliminates having to write a unit test to make sure a value is lazy loaded.
Using this Lazy class on a class variable would look like the following:
// Java code
public final class UserService {
private final Lazy<User> admin = Lazy.load(
() -> userDao.findAdmin("admin")
);
public User admin() {
return admin.get();
}
}
This Lazy class uses a static factory method for creating instances. The API (Application Programming Interface) reads much better than creating instances with new. An example of if you were using new would look like the following:
// Java code
private final Lazy<User> admin = new Lazy<>(
() -> userDao.find("admin")
)
This doesn't read as well as the static load() method does.
Conclusion
Use Lazy instead of writing the same if statement each time you have to lazy load something. The code reads better, and you eliminate the if statement and extra unit tests.