mirror of
https://github.com/DesignPatternsPHP/DesignPatternsPHP.git
synced 2025-09-25 13:59:08 +02:00
Previous example was simply implementing a strategy pattern. A key problem is that WebService made clear that it did no actual output of its own - it handed it off to 'decorators'. A decorator should always wrap a class that already has its own complete, self-contained functionality. In this way, they only enhance / modify it. An instance that is non-decorated should work fully by itself. Note the distinguishing difference between this and sub-classing - here the enhancement is added dynamically, at runtime, and to one instance. With sub-classing, the enhancement is added at compile / parse time, and is applied to all instances / uses of the subclass.
75 lines
1.5 KiB
PHP
75 lines
1.5 KiB
PHP
<?php
|
|
|
|
namespace DesignPatterns;
|
|
|
|
/**
|
|
* Decorator pattern
|
|
*
|
|
* Purpose:
|
|
* to dynamically add new functionality to class instances
|
|
*
|
|
* Examples:
|
|
* - Zend Framework: decorators for Zend_Form_Element instances
|
|
* - Web Service Layer: Decorators JSON and XML for a REST service (in this case, only one of these should be allowed of
|
|
* course)
|
|
*
|
|
*/
|
|
|
|
interface Renderer
|
|
{
|
|
public function renderData();
|
|
}
|
|
|
|
class Webservice implements Renderer
|
|
{
|
|
protected $_data;
|
|
|
|
public function __construct($data)
|
|
{
|
|
$this->_data = $data;
|
|
}
|
|
|
|
public function renderData()
|
|
{
|
|
return $this->_data;
|
|
}
|
|
}
|
|
|
|
abstract class Decorator
|
|
{
|
|
protected $_wrapped;
|
|
|
|
public function __construct($wrappable)
|
|
{
|
|
$this->_wrapped = $wrappable;
|
|
}
|
|
}
|
|
|
|
class RenderInJson extends Decorator implements Renderer
|
|
{
|
|
public function renderData()
|
|
{
|
|
$output = $this->_wrapped->renderData();
|
|
return json_encode($output);
|
|
}
|
|
}
|
|
|
|
class RenderInXml extends Decorator implements Renderer
|
|
{
|
|
public function renderData()
|
|
{
|
|
$output = $this->_wrapped->renderData();
|
|
// do some fany conversion to xml from array ...
|
|
return simplexml_load_string($output);
|
|
}
|
|
}
|
|
|
|
// Create a normal service
|
|
$service = new Webservice(array('foo' => 'bar'));
|
|
|
|
// Wrap service with a JSON decorator for renderers
|
|
$service = new RenderInJson($service);
|
|
// Our Renderer will now output JSON instead of an array
|
|
|
|
echo $service->renderData();
|