2.5. Dekorator (Decorator)¶
2.5.1. Przeznaczenie¶
Pozwala na dynamiczne dodawanie nowych funkcji do istniejących klas podczas działania programu.
2.5.2. Przykłady¶
- Zend Framework: dekoratory do obiektów klasy
Zend_Form_Element
. - Web Service Layer: Dekorator typu JSON i XML używany w usłudze typu REST (w tym przykładzie tylko jeden z nich powinien być dozwolony).
2.5.3. Diagram UML¶

2.5.4. Kod¶
Ten kod znajdziesz również na GitHub.
RenderableInterface.php
1 2 3 4 5 6 7 8 | <?php
namespace DesignPatterns\Structural\Decorator;
interface RenderableInterface
{
public function renderData(): string;
}
|
Webservice.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <?php
namespace DesignPatterns\Structural\Decorator;
class Webservice implements RenderableInterface
{
/**
* @var string
*/
private $data;
public function __construct(string $data)
{
$this->data = $data;
}
public function renderData(): string
{
return $this->data;
}
}
|
RendererDecorator.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 | <?php
namespace DesignPatterns\Structural\Decorator;
/**
* the Decorator MUST implement the RenderableInterface contract, this is the key-feature
* of this design pattern. If not, this is no longer a Decorator but just a dumb
* wrapper.
*/
abstract class RendererDecorator implements RenderableInterface
{
/**
* @var RenderableInterface
*/
protected $wrapped;
/**
* @param RenderableInterface $renderer
*/
public function __construct(RenderableInterface $renderer)
{
$this->wrapped = $renderer;
}
}
|
XmlRenderer.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <?php
namespace DesignPatterns\Structural\Decorator;
class XmlRenderer extends RendererDecorator
{
public function renderData(): string
{
$doc = new \DOMDocument();
$data = $this->wrapped->renderData();
$doc->appendChild($doc->createElement('content', $data));
return $doc->saveXML();
}
}
|
JsonRenderer.php
1 2 3 4 5 6 7 8 9 10 11 | <?php
namespace DesignPatterns\Structural\Decorator;
class JsonRenderer extends RendererDecorator
{
public function renderData(): string
{
return json_encode($this->wrapped->renderData());
}
}
|
2.5.5. Testy¶
Tests/DecoratorTest.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 28 29 30 31 32 33 | <?php
namespace DesignPatterns\Structural\Decorator\Tests;
use DesignPatterns\Structural\Decorator;
use PHPUnit\Framework\TestCase;
class DecoratorTest extends TestCase
{
/**
* @var Decorator\Webservice
*/
private $service;
protected function setUp()
{
$this->service = new Decorator\Webservice('foobar');
}
public function testJsonDecorator()
{
$service = new Decorator\JsonRenderer($this->service);
$this->assertEquals('"foobar"', $service->renderData());
}
public function testXmlDecorator()
{
$service = new Decorator\XmlRenderer($this->service);
$this->assertXmlStringEqualsXmlString('<?xml version="1.0"?><content>foobar</content>', $service->renderData());
}
}
|