Null Object Pattern
Purpose
The purpose of the design pattern
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
Examples of how the design pattern can be used
- 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
UML design pattern diagram

Code
Code snippets
Service
Service class accepts a Logger via its construct, the doSomething method calls the log method contained within the Logger instance.
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
Logger interface that NullLogger and PrintLogger implement, ensuring these concrete classes have a log method.
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
NullLogger implements Logger (but does nothing)
namespace DesignPatterns\Behavioral\NullObject;
class NullLogger implements Logger
{
public function log(string $str)
{
// do nothing
}
}
Print Logger
PrintLogger implements Logger
namespace DesignPatterns\Behavioral\NullObject;
class PrintLogger implements Logger
{
public function log(string $str)
{
echo $str;
}
}
Tests
Unit tests showing the code above in action. Instead of a method which returns an object or null, you’d always return an object (and if required a null object). This approach also doesn’t break the Liskov Substitution Principle (LSP).
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.