In this post I will summarise the Null Object Pattern.
The null object pattern is a means to forgo null checks. The following example will be used to explain how the null object pattern can be used to reach this goal.
public Person getPerson() { return person; } public void showName() { Person person = getPerson(); String name = "unknown"; if (person != null) { name = person.getName(); } System.out.println("name: " + name); }
In my opinion a few there are thing wrong with this code.
- Different call flow. Because of the null check there are two possible paths through this code. If this is the only point at which this occurs, it would not be a big problem. But
- Caller is responsible. The caller is made responsible to check if the returned value is correct. By placing the burden at the callers side probably means a lot of duplicate boilerplate code in checking for null values.
- Error prone. You only have to forget the null check once and it will blow up in your face with a NullPointerException.
The null object pattern is a means to remedy these points. In the following example I refactored the original code.
class UnknownPerson extends Person { @Override public String getName() { return "unknown"; } } public Person getPerson() { if (person == null) { return new UnknownPerson(); } return person; } public void showName() { Person person = getPerson(); System.out.println("name: " + person.getName()); }
With the introduction of the UnknownPerson all the mentioned problems are solved.
- Same call flow. The calling code does not have to differentiate between a null value and a legitimate value
- Callee is responsible. The callee is now responsible to check if the returned value is defined. By placing the burden at the callee side there is a single check so no duplication of code. So
- Less error prone. Because the null check is in a single location there are less oppertunities for making a mistake.
This summarises the null object pattern.
No comments:
Post a Comment