3.7. Null Object
3.7.1. Scopo
NullObject non è un pattern della GoF ma uno schema che appare frequentemente da essere considerato tale. Possiede i seguenti vantaggi:
Il codice del client è semplificato
Riduce il rischio di null pointer exceptions
Meno espressioni condizionali richiedono meno casi di test
I metodi che restituisco un oggetto o null dovrebbero invece restituire l’oggetto o il NullObject. Questi NullObjects semplificano il codice cosicchè if (!is_null($obj)) { $obj->callSomething() ; } con il seguente $obj->callSomething() ; eliminado il controllo condizionale nel codice del client.
3.7.2. Esempi
Null logger or null output to preserve a standard way of interaction between objects, even if the shouldn’t do anything
Null handler in un pattern di Chain of Responsabilities
Null command in un Command pattern
3.7.3. Diagramma UML
3.7.4. Codice
Potete trovare questo codice anche su GitHub
Service.php
1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Behavioral\NullObject;
6
7class Service
8{
9 public function __construct(private Logger $logger)
10 {
11 }
12
13 /**
14 * do something ...
15 */
16 public function doSomething()
17 {
18 // notice here that you don't have to check if the logger is set with eg. is_null(), instead just use it
19 $this->logger->log('We are in ' . __METHOD__);
20 }
21}
Logger.php
1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Behavioral\NullObject;
6
7/**
8 * Key feature: NullLogger must inherit from this interface like any other loggers
9 */
10interface Logger
11{
12 public function log(string $str);
13}
PrintLogger.php
1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Behavioral\NullObject;
6
7class PrintLogger implements Logger
8{
9 public function log(string $str)
10 {
11 echo $str;
12 }
13}
NullLogger.php
1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Behavioral\NullObject;
6
7class NullLogger implements Logger
8{
9 public function log(string $str)
10 {
11 // do nothing
12 }
13}
3.7.5. Test
Tests/LoggerTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Behavioral\NullObject\Tests;
6
7use DesignPatterns\Behavioral\NullObject\NullLogger;
8use DesignPatterns\Behavioral\NullObject\PrintLogger;
9use DesignPatterns\Behavioral\NullObject\Service;
10use PHPUnit\Framework\TestCase;
11
12class LoggerTest extends TestCase
13{
14 public function testNullObject()
15 {
16 $service = new Service(new NullLogger());
17 $this->expectOutputString('');
18 $service->doSomething();
19 }
20
21 public function testStandardLogger()
22 {
23 $service = new Service(new PrintLogger());
24 $this->expectOutputString('We are in DesignPatterns\Behavioral\NullObject\Service::doSomething');
25 $service->doSomething();
26 }
27}