# Null Object Pattern

version 2.3.7

The Null Object Pattern involves using a special object place-marker object representing null. Typically, if you have a reference to null, you can’t invoke `reference.field` or `reference.method()`. You receive the dreaded `NullPointerException`. The null object pattern uses a special object representing null, instead of using an actual `null`. This allows you to invoke field and method references on the null object. The result of using the null object should semantically be equivalent to doing nothing.

## 1. Simple Example

Suppose we have the following system:

    class Job {
        def salary
    }

    class Person {
        def name
        def Job job
    }

    def people = [
        new Person(name: 'Tom', job: new Job(salary: 1000)),
        new Person(name: 'Dick', job: new Job(salary: 1200)),
    ]

    def biggestSalary = people.collect { p -> p.job.salary }.max()
    println biggestSalary

When run, this prints out `1200`. Suppose now that we now invoke:

    people << new Person(name: 'Harry')

If we now try to calculate `biggestSalary` again, we receive a null pointer exception.

To overcome this problem, we can introduce a `NullJob` class and change the above statement to become:

    class NullJob extends Job { def salary = 0 }

    people << new Person(name: 'Harry', job: new NullJob())
    biggestSalary = people.collect { p -> p.job.salary }.max()
    println biggestSalary

This works as we require but it’s not always the best way to do this with Groovy. Groovy’s safe-dereference operator (`?.`) operator and null aware closures often allow Groovy to avoid the need to create a special null object or null class. This is illustrated by examining a groovier way to write the above example:

    people << new Person(name:'Harry')
    biggestSalary = people.collect { p -> p.job?.salary }.max()
    println biggestSalary

Two things are going on here to allow this to work. First of all, `max()` is 'null aware’ so that `[300, null, 400].max() == 400`. Secondly, with the `?.` operator, an expression like `p?.job?.salary` will be equal to null if `salary` is equal to null, or if `job` is equal to null or if `p` is equal to null. You don’t need to code a complex nested `if … then … else` to avoid a `NullPointerException`.

## 2. Tree Example

Consider the following example where we want to calculate size, cumulative sum and cumulative product of all the values in a tree structure.

Our first attempt has special logic within the calculation methods to handle null values.

    class NullHandlingTree {
        def left, right, value

        def size() {
            1 + (left ? left.size() : 0) + (right ? right.size() : 0)
        }

        def sum() {
           value + (left ? left.sum() : 0) + (right ? right.sum() : 0)
        }

        def product() {
           value * (left ? left.product() : 1) * (right ? right.product() : 1)
        }
    }

    def root = new NullHandlingTree(
        value: 2,
        left: new NullHandlingTree(
            value: 3,
            right: new NullHandlingTree(value: 4),
            left: new NullHandlingTree(value: 5)
        )
    )

    println root.size()
    println root.sum()
    println root.product()

If we introduce the null object pattern (here by defining the `NullTree` class), we can now simplify the logic in the `size()`, `sum()` and `product()` methods. These methods now much more clearly represent the logic for the normal (and now universal) case. Each of the methods within `NullTree` returns a value which represents doing nothing.

    class Tree {
        def left = new NullTree(), right = new NullTree(), value

        def size() {
            1 + left.size() + right.size()
        }

        def sum() {
           value + left.sum() + right.sum()
        }

        def product() {
           value * left.product() * right.product()
        }
    }

    class NullTree {
        def size() { 0 }
        def sum() { 0 }
        def product() { 1 }
    }

    def root = new Tree(
        value: 2,
        left: new Tree(
            value: 3,
            right: new Tree(value: 4),
            left: new Tree(value: 5)
        )
    )

    println root.size()
    println root.sum()
    println root.product()

The result of running either of these examples is:

    4
    14
    120

Note: a slight variation with the null object pattern is to combine it with the singleton pattern. So, we wouldn’t write `new NullTree()` wherever we needed a null object as shown above. Instead we would have a single null object instance which we would place within our data structures as needed.