3.6. Null Object
3.6.1. Purpose
NullObject is not a GoF design pattern but a schema which appearsfrequently enough to be considered a pattern. It has the followingbenefits:
- 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 orNullObject
.NullObject
s simplify boilerplate code such asif (!is_null($obj)) { $obj->callSomething(); }
to just$obj->callSomething();
by eliminating the conditional check inclient code.
3.6.2. Examples
- Symfony2: null logger of profiler
- Symfony2: null output in Symfony/Console
- null handler in a Chain of Responsibilities pattern
- null command in a Command pattern
3.6.3. UML Diagram
3.6.4. Code
You can also find this code on GitHub
Service.php
- <?php
- namespace DesignPatterns\Behavioral\NullObject;
- class Service
- {
- /**
- * @var LoggerInterface
- */
- private $logger;
- /**
- * @param LoggerInterface $logger
- */
- public function __construct(LoggerInterface $logger)
- {
- $this->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__);
- }
- }
LoggerInterface.php
- <?php
- namespace DesignPatterns\Behavioral\NullObject;
- /**
- * Key feature: NullLogger must inherit from this interface like any other loggers
- */
- interface LoggerInterface
- {
- public function log(string $str);
- }
PrintLogger.php
- <?php
- namespace DesignPatterns\Behavioral\NullObject;
- class PrintLogger implements LoggerInterface
- {
- public function log(string $str)
- {
- echo $str;
- }
- }
NullLogger.php
- <?php
- namespace DesignPatterns\Behavioral\NullObject;
- class NullLogger implements LoggerInterface
- {
- public function log(string $str)
- {
- // do nothing
- }
- }
3.6.5. Test
Tests/LoggerTest.php
- <?php
- namespace DesignPatterns\Behavioral\NullObject\Tests;
- use DesignPatterns\Behavioral\NullObject\NullLogger;
- use DesignPatterns\Behavioral\NullObject\PrintLogger;
- use DesignPatterns\Behavioral\NullObject\Service;
- use PHPUnit\Framework\TestCase;
- class LoggerTest extends TestCase
- {
- 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();
- }
- }