Null Object

Intent

Provide a surrogate for another object that shares the same interface but does nothing.

The Null Object encapsulates the implementation decisions of how to do nothing and hides those details from its collaborators.

Motivation

  • Sometimes, a client requests a behavior from a collaborator class

  • The collaborator class is optional: if it is not present, the expected behavior is to do nothing

  • The client wants to use the the collaborator transparently, without checking for nulls every time.

Motivation Example

  • Consider a logging facility with two implementations: file and console logging

  • Services can use either implementations.

  • However, a service is not necessarily required to use a log (the association between Service and Log is optional)

  • Therefore, the Service must check for null values before using the log

Diagram

Applicability

Use the Null Object pattern when:
  • an object requires a collaborator and

  • some collaborator instances may be null and

  • collaborator instances must be checked before every use and

  • the result of a null check is to do nothing or execute a default behavior

Solution

  • Create a class that implements the same interface as the collaborator class and

  • Implement all its methods to do nothing or provide default results and

  • Use an instance of this class whenever the collaborator reference would have been null

Structure

Diagram
Participants
Client

requires a collaborator

Abstract Collaborator

declares a common interface for collaborators

Actual Collaborator

provides the actual behavior that the Client expects

Null Collaborator

does nothing.

Doing nothing depends on the behavior the Client is expecting. When there is more than one way of doing nothing, more than one Null Collaborator may be required.

Consequences

  • Clients ignore if they are working with null objects

  • The client code is simpler

  • The null/default behavior is encapsulated in a single class

  • This behavior can be shared with other classes

  • Null values are typed

  • May need to create a Null Collaborator for every new abstract class

  • Hard to implement if clients do not agree on what the null behavior should do

  • Always acts as a Null Collaborator, cannot be transformed into an Actual Collaborator

Implementation Tradeoffs

  • The Null Object is often a Singleton

  • Use the Null Object as special Strategy.

  • Use the Null Object as special State.

  • Use the Optional interface in Java

Java Code Example (1/2)

AbstractCustomer
public abstract class AbstractCustomer {
   protected String name;
   public abstract boolean isNil();
   public abstract String getName();
}
RealCustomer
public class RealCustomer extends AbstractCustomer {
   public RealCustomer(String name) {
      this.name = name;
   }
   @Override
   public String getName() {
      return name;
   }
   @Override
   public boolean isNil() {
      return false;
   }
}

Java Code Example (1/2)

NullCustomer
public class NullCustomer extends AbstractCustomer {
   @Override
   public String getName() {
      return "Not Available in Customer Database";
   }
   @Override
   public boolean isNil() {
      return true;
   }
}
CustomerFactory
public class CustomerFactory {
   public static final String[] names = {"Rob", "Joe", "Julie"};

   public static AbstractCustomer getCustomer(String name){
      for (int i = 0; i < names.length; i++) {
         if (names[i].equalsIgnoreCase(name)){
            return new RealCustomer(name);
         }
      }
      return new NullCustomer();
   }
}

Java Optionals

Optional Interface usage
Optional.empty() : Optional<T> (1)
Optional.of(T t) : Optional<T> (2)
Optional.ofNullable(T t) : Optional<T> (3)
1Returns an Optional with no value
2Returns an Optional with the value t
3Returns an Optional that may contain a value (calls empty() or of(T) depending whether t is null)

Java Optionals Example

class Main {
  Optional<Customer> customer = Optional.empty();

  public void setCustomer(Customer c) {
    customer = Optional.ofNullable(c);
  }

  public void print() {
    customer.ifPresent(each => System.out.println(each))
  }
}

Authors and Date

  • "Null Object — Something for Nothing". Kevlin Henney, March 2003.

  • "The Null Object Pattern". Bobby Woolf, July 1996.

  • "Smart Nil". Panu Viljamaa, 1997

  • "Null Object Pattern". Jeffery Walker, 2002.

Other Examples

Empty lists in Java

Diagram
Collections class (Open JDK)
public class Collections {
    public static final List EMPTY_LIST = new EmptyList<>();
    public static final <T> List<T> emptyList() {
        return (List<T>) EMPTY_LIST;
    }

    private static class EmptyList<E>
        extends AbstractList<E>
        implements RandomAccess, Serializable {
    // (...)
        public int size() {return 0;}
        public boolean isEmpty() {return true;}
        public void clear() {}
        public boolean contains(Object obj) {return false;}
        public boolean containsAll(Collection<?> c) { return c.isEmpty(); }
    }
}

Null Object