Null Object Pattern

Purpose

NullObject is not a GoF (gang of four) design pattern but a schema which appears frequently enough to be considered a pattern. It has the following benefits:

  • Client code is simplified
  • Reduces the chance of null pointer exceptions
  • Fewer conditionals require less test cases

Methods that return an object or null should instead return an object or NullObject.

NullObjects simplify boilerplate code such as if (!is_null($obj)) { $obj->callSomething(); to just: $obj->callSomething(); by eliminating the conditional check in client code.

Examples
  • Null logger or null output to preserve a standard way of interaction between objects, even if the shouldn't do anything
  • Null handler in a Chain of Responsibilities pattern
  • Null command in a Command pattern
UML


Code

Service


namespace DesignPatterns\Behavioral\NullObject;

class Service
{
    public function __construct(private Logger $logger)
    {
    }

    /**
     * do something ...
     */
    public function doSomething()
    {
        // notice here that you don't have to check if the logger is set with eg. is_null(), instead just use it
        $this->logger->log('We are in ' . __METHOD__);
    }
}

Logger


namespace DesignPatterns\Behavioral\NullObject;

/**
* Key feature: NullLogger must inherit from this interface like any other loggers
*/
interface Logger
{
    public function log(string $str);
}

Null Logger


namespace DesignPatterns\Behavioral\NullObject;

class NullLogger implements Logger
{
    public function log(string $str)
    {
        // do nothing
    }
}

Print Logger


namespace DesignPatterns\Behavioral\NullObject;

class PrintLogger implements Logger
{
    public function log(string $str)
    {
        echo $str;
    }
}

Tests


public function testNullObject()
{
    $service = new Service(new NullLogger());
    $this->expectOutputString('');
    $service->doSomething();
}

public function testStandardLogger()
{
    $service = new Service(new PrintLogger());
    $this->expectOutputString('We are in DesignPatterns\Behavioral\NullObject\Service::doSomething');
    $service->doSomething();
}

Ready to bring your vision to life?

We believe in excellence, empathy, integrity, and transparency throughout the process. Our goal is to build fast, responsive websites that not only perform but also reflect your values and vision.