Null object pattern

This little and easy to use pattern is very useful, but still unknown to many people. Maybe it’s because when someone says “pattern”, we automatically think of patterns invented by the Gang of Four. Even if this one is not part of the original 23 GoF design patterns, it’s worth taking a look at it, since it can make design more clear.

So, what’s Null Object Pattern (or Empty Object Pattern, as a colleague of mine suggested at a session where I presented this pattern) is all about? Let’s suppose we are given an application which reads data from a database (as a response to a search, initiated through a GUI), after which it passes the data through several layers and presents the result on the GUI. Let’s  say the above mentioned data object is of type User. Now, what happens if there are no results to the query? In a classical design, that might result in a null value returned . From that point on, every single layer might check whether the object they are working with is null or not. If it is null, the current method further returns a null value, or works with it otherwise. The logic


if (user == null) {

    return null;

} else {

    //...do something useful

}

is duplicated over and over again through each and every layer of the application. It is necessary, after all, or else the application will throw a beautiful NullPointerException.

How can we avoid these if-else statements? Easy; imagine the following class hierarchy:
As you can see, we have refactored the User class, and made it an interface (or abstract class, if you wish). This way you don’t need to touch any of the methods’ return statements (of course you don’t need to call the concrete class ConcreteUser). Now, the implementation of the User class is moved down into ConcreteUser. As EmptyUser is also implementing (or extending) User, it has to implement all the methods defined in User. And now, the trick: we implement all the methods with an empty body. That’s right; a body with no statements at all. So, EmptyUser would look something like this, in our case:

public class EmptyUser implements User{
    public EmptyUser() {
        //...
    }

    public void method1() {
    }

    public void method2() {
    }
}

So what’s the benefit? When our database query returns null (remember, we have to check here that the returned value is null or not), we don’t push it forward. We simply instantiate an EmptyUser object, which will be safe to call any method on. This way we can eliminate each and every if-null constructs (but the first). The design can now focus on the logic itself, rather than keeping doing null checks.

A very simple exercise on Null Object Pattern you can try at home; given an object called Book. A book has an author, a title and a getInfo() method, which can return some basic book info, in the format:

Author: Gabriel Garcia Marquez

Title: One hundred years of solitude

You are also given a “library”, in form of a hash map; the key is an ISBN number, the value is a Book object. Your task is to implement the LibraryInfo interface, defined as:

 public interface LibraryInfo {

	boolean isIsbnValid(final String isbn);
	Book getBook(final String isbn);
	StringBuilder getBookInfo(final String[] isbns);
 }

isIsbnValid is pretty straightforward. It returns true if an ISBN value is valid, false otherwise.
getBook: if the ISBN number passed in as a parameter is valid, and the ISBN can be found in the library (the hash map, remember?) it returns the book found. NOT NULL otherwise 🙂
getBookInfo: checks ISBN numbers, queries the library for them and appends together all the resulting book information (remember that you don’t have to check for nulls at all here)

Don’t forget to use the Null Object Pattern

Advertisements

Author: tamasgyorfi

Senior software engineer, certified enterprise architect and certified Scrum master. Feel free to connect on Twitter: @tamasgyorfi

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s