Skip to content

Null Object Pattern

Last updated on April 3, 2019

Almost every method that we write, irrespective of the programming language, we always have checks like the following one:

if (objectVariable == null)
    return;
// do some work with objectVariable

We end up adding so many null checks in our methods, that it gets almost hard to figure out what we are supposed to do in our method. This makes our code look ugly and hard to read.

 

Scenario

Consider a simple console application which uses an IMobile type to perform some operations. The IMobile type is returned from a MobileRepository using a method named GetMobileByName(mobileName), where mobileName is the name of the mobile that we wish to operate on.

A code implementing the above requirement would look something like the following:

class Program
{
    static void Main(string[] args)
    {
        var mobileRepository = new MobileRepository();
        IMobile mobile = mobileRepository.GetMobileByName("sony");
        mobile.TurnOn();
        mobile.TurnOff();
     }
}

 

Now in this code, as we are not having a null check for the object returned by MobileRepository, we might get a NullreferenceExceptionfor some invalid input to the method GetMobileByName. In this case, we can solve this problem by simply introducing a null check for mobile.

But is it really a good solution? What if the GetMobileByName is being used in several methods. Would it be feasible to add a null check in every method? Well, a better alternative is to implement Null Object pattern.

 

What is Null Object pattern?

The null object is also known as a Stub, an Active Nothing and an Active Null. It helps our program logic to get rid of null checks where ever possible. We all know, that we can not call methods on a null reference as it results in a NullReferenceException. The null object pattern provides a non-functional object in place of a null reference and therefore allows methods to be called on it.

So, for some invalid input to the method GetMobileByName, our MobileRepository would return an instantiated, yet null, IMobile object in place of a null reference. Unlike any other Mobile object, when we perform any operation on this object, nothing would happen.

 

Implementation

As discussed above, in our scenario we have to implement the method GetMobileByName in a way that it shall return a null IMobile object in place of a null reference, for any invalid input. In order to achieve that, we first need to create a class implementing from the IMobile interface. The object of this class would be our null object implementation. Please refer the following code for the same:

public interface IMobile
{
    void TurnOn();
    void TurnOff();
}

//mobile type implementing IMobile interface
public class SamsungGalaxy : IMobile
{
    public void TurnOff()
    {
        Console.WriteLine("\nSamsung Galaxy Turned OFF!");
    }

    public void TurnOn()
    {
        Console.WriteLine("\nSamsung Galaxy Turned ON!");
    }
}

//our null object class implementing IMobile interface as a singleton
public class NullMobile : IMobile
{
    private static NullMobile _instance;
    private NullMobile()
    { }

    public static NullMobile Instance
    {
        get {
            if (_instance == null)
                return new NullMobile();
            return _instance;
        }
    }

    //do nothing methods
    public void TurnOff()
    { }

    public void TurnOn()
    { }
}

 

Our repository can return different types of mobiles like SamsungGalaxy, AppleIPhone and SonyXperia. All the types implement the IMobile interface. Our null object class, NullMobile is a classic Singleton and implements from IMobile interface. In the above code, we can see that, the NullMobile class like other types, implements the methods TurnOn and TurnOff. However, the method implementations do nothing.

Now, that we have our null object ready, it’s time to use it at the right place. We do not want to have any null check for the type returned from the repository in the main logic. Therefore, our MobileRepository shall return a NullMobile instance in place of a null reference for any invalid input. Let’s have a look how it works in code:

public class MobileRepository
{
    public IMobile GetMobileByName(string mobileName)
    {
        IMobile mobile = NullMobile.Instance;
        switch (mobileName)
        {
            case "sony":
                mobile = new SonyXperia();
                break;

            case "apple":
                mobile = new AppleIPhone();
                break;

            case "samsung":
                mobile = new SamsungGalaxy();
                break;
        }
        return mobile;
    }
}

We have first created a variable of type IMobile and initialized it with an instance of NullMobile. If the mobileName does not match a case in the switch statement, the NullMobile object is returned by the GetMobileByName method. In our main logic, when we try to call methods on this object we will not get any exception and hence the work flow will not break. However, the methods will do nothing.

 

Summary

  • The null object pattern helps us to write a clean code avoiding null checks where ever possible.
  • Using the null object pattern, the callers do not have to care whether they have a null object or a real object.
  • It is not possible to implement null object pattern in every scenario. Sometimes, it is likely to return a null reference and perform some null checks.
  • In above code sample, we are using an null object implementing an interface. However, we can have a quite similar approach with Abstract base class also.
  • Null object is often a singleton. However, sometimes we want our object state to vary over instances.
  • Null pattern is helpful in situations where we want to return an object of the expected type, yet do nothing.
  • It is important to note that unless developers are aware that the null object implementation exists, they may still do null checks.

 

I hope this helps you get a basic understanding about the null object pattern and how it helps you write a clean code. It’s always great to have feedback from the readers. Your valuable feedback, question, or comments about this article are always welcome.

Published in.Net Core