start a restructure

This commit is contained in:
Antonio Spinelli
2014-03-21 18:03:44 -03:00
parent b0b0d4a1a4
commit e59d70a0ac
180 changed files with 21 additions and 16 deletions

View File

@@ -0,0 +1,18 @@
<?php
namespace DesignPatterns\NullObject;
/**
* LoggerInterface is a contract for logging something
*
* Key feature: NullLogger MUST inherit from this interface like any other Loggers
*/
interface LoggerInterface
{
/**
* @param string $str
*
* @return mixed
*/
public function log($str);
}

View File

@@ -0,0 +1,21 @@
<?php
namespace DesignPatterns\NullObject;
/**
* Performance concerns : ok there is a call for nothing but we spare an "if is_null"
* I didn't run a benchmark but I think it's equivalent.
*
* Key feature : of course this logger MUST implement the same interface (or abstract)
* like the other loggers.
*/
class NullLogger implements LoggerInterface
{
/**
* {@inheritdoc}
*/
public function log($str)
{
// do nothing
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace DesignPatterns\NullObject;
/**
* PrintLogger is a logger that prints the log entry to standard output
*/
class PrintLogger implements LoggerInterface
{
/**
* @param string $str
*/
public function log($str)
{
echo $str;
}
}

View File

@@ -0,0 +1,20 @@
# Null Object
## Purpose
NullOutput is a example of NullObject pattern. It is not formally a Design Pattern by the GoF but it's a schema which appears frequently enough to
be a pattern. Furthermore it is a really good pattern in my opinion:
* the code in the client is simple
* it reduces the chance of null pointer exception
* less "if" => less test cases
Every time you have a method which returns an object or null, you should return an object or a `NullObject`. With NullObject, you don't need
a statement like `if (!is_null($obj)) { $obj->callSomething(); }` anymore.
## 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

View File

@@ -0,0 +1,34 @@
<?php
namespace DesignPatterns\NullObject;
/**
* Service is dummy service that uses a logger
*/
class Service
{
/**
* @var LoggerInterface
*/
protected $logger;
/**
* we inject the logger in ctor and it is mandatory
*
* @param LoggerInterface $log
*/
public function __construct(LoggerInterface $log)
{
$this->logger = $log;
}
/**
* do something ...
*/
public function doSomething()
{
// no more check "if (!is_null($this->logger))..." with the NullObject pattern
$this->logger->log('We are in ' . __METHOD__);
// something to do...
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace DesignPatterns\Tests\NullObject;
use DesignPatterns\NullObject\NullLogger;
use DesignPatterns\NullObject\Service;
use DesignPatterns\NullObject\PrintLogger;
/**
* LoggerTest tests for different loggers
*/
class LoggerTest extends \PHPUnit_Framework_TestCase
{
public function testNullObject()
{
// one can use a singleton for NullObjet : I don't think it's a good idea
// because the purpose behind null object is to "avoid special case".
$service = new Service(new NullLogger());
$this->expectOutputString(null); // no output
$service->doSomething();
}
public function testStandardLogger()
{
$service = new Service(new PrintLogger());
$this->expectOutputString('We are in DesignPatterns\NullObject\Service::doSomething');
$service->doSomething();
}
}