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