Полагаю сам декоратор а так же причины по которым использование этого шаблона предпочтительней классическому наследованию в описании не нуждаются. При желании о нем можно прочитать в английской или русской википедии. Поэтому сама статья — это всего лишь мои соображений по поводу одной из возможных реализаций этого шаблона а именно динамического декорирования в противовес широко распространенной технике статического декорирования.
Преимущество динамического декорирования над статическим — это отсутствие необходимости создания специальных классов декораторов. В данном случае все что нужно для того чтобы PHP класс мог быть декорируемым — это использовать соотвествующую примесь.
В английской статье Википедии про декоратор (ссылка выше) есть Java пример использования статического декорирования в реализации оконного интейрфеса. По аналогии того примера, но без использования классов декораторов:
class Window
{
use TDecorator;
private $title;
function __construct($title)
{
$this->title = $title;
}
function draw()
{
// Draws window below
// ...
// Draws decorations.
$this->renderDecoration('draw');
}
}
class VerticalScrollbar
{
use TDecoration;
private $vWidth;
private $vHeight;
function __construct($width, $height)
{
$this->vWidth = $width;
$this->vHeight = $height;
}
function draw()
{
echo 'Drawing vertical scrollbar for the window "' . $this->title . ""n";
echo 'Width: ' . $this->vWidth . "pxn";
echo 'Height: ' . $this->vHeight . "pxn";
}
}
// Decorates window with a vertical scrollbar.
$wnd = new Window('My application');
$wnd->decorateWithObject(new VerticalScrollbar(20, 20));
$wnd->draw();
При декорировании одного объекта другим он получает доступ не только ко всем его публичным и частным методам, но так же и свойствам вместе с их значениями. Можно сказать что таким способом класс VerticalScrollbar наследовал класс Window, но только для одного объекта.
Помимо декорирования одного объекта другим есть и более простая возможно добавлять новое поведение:
class Integer
{
use TDecorator;
protected $value;
function __construct($value)
{
$this->value = intval($value);
}
}
$integer = new Integer(9);
$integer->decorateWith('isOdd', function() {
return (boolean) ($this->value % 2);
});
echo $integer->isOdd(); // echoes true
Реализацию декоратора в виде примеси можно найти здесь.
Надеюсь это небольшая статья кому-нибудь окажется полезной.
Автор: AccessGranted