3.7. Null Object

3.7.1. Amaç

Boş Nesne, bir Dörtlü Takım (Gang of Four) tasarım deseni değildir. Ancak, bir şemadır ve görünen o ki sıklıkla bir desen olarak ele alınmaktadır.Aşağıdaki yararlıklara sahiptir:

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

Bir nesne veya boş (null) döndüren nesneler, bunun yerine yine bir nesne veya NullObject döndürür. NullObject, istemci kodundaki koşullu kontrolü (if) atarak, yani if (!is_null($object)) $object->callSomething() yerine yalnızca $object->callSomething() kısmının kullanılabilmesini sağlayarak, ortak kodu (boilerplate) basitleştirmiştir.

3.7.2. Örnekler

  • 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

3.7.3. UML Diyagramı

Alt NullObject UML Diagram

3.7.4. Kod

Bu kodu Github üzerinde de bulabilirsiniz.

Service.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<?php

declare(strict_types=1);

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.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<?php

declare(strict_types=1);

namespace DesignPatterns\Behavioral\NullObject;

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

PrintLogger.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<?php

declare(strict_types=1);

namespace DesignPatterns\Behavioral\NullObject;

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

NullLogger.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<?php

declare(strict_types=1);

namespace DesignPatterns\Behavioral\NullObject;

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

3.7.5. Test

Tests/LoggerTest.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php

declare(strict_types=1);

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();
    }
}