PHP 空对象模式
目的
空对象模式不是一个GoF设计模式,但是它出现非常频繁足以被认为是设计模式。它的好处如下:
- 简化客户端代码
- 减少空指针异常的次数
- 减少测试用例的复杂性
返回一个对象或null的方法应该返回一个对象或NullObject。NullObjects简化了样板代码,如if (!is_null($obj)) {$obj->callSomething();}只需要$obj->callSomething();通过消除客户端代码中的条件签入。
例子
- Null logger或Null输出以保持对象之间交互的标准方式,即使他们不做任何事情
- 责任链模式中的空处理程序
- 命令模式中的空命令
UML 图
代码
Service.php
<?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
<?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
<?php declare(strict_types=1); namespace DesignPatterns\Behavioral\NullObject; class PrintLogger implements Logger { public function log(string $str) { echo $str; } }
NullLogger.php
<?php declare(strict_types=1); namespace DesignPatterns\Behavioral\NullObject; class NullLogger implements Logger { public function log(string $str) { // do nothing } }
测试
Tests/LoggerTest.php
<?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(); } }