Pattern: Decorator
Сколько раз обещаю себе больше не писать на PHP, и всеравно пишу. Вот и недавно разродился небольшим классом реализующим шаблон декоратор.
class Decorator {
protected $obj;
public function __construct($name,$args=null){
if (is_object($name)) {
$this->obj = $name;
} else if($args) {
$reflection = new ReflectionClass($name);
$this->obj = $reflection->newInstanceArgs($args);
} else {
$this->obj = new $name;
}
}
public function __call($name,$args){
if($args)
return call_user_func_array(array($this->obj,$name), $args);
else
return $this->obj->{$name}();
}
}
Все началось как пример одному долбаёбу на форуме, а закончилось как небольшой но прикольный класс. Естественно сначала я пару раз переписал пример, потом потестил его на локальном сервере и только потом написал эту статью, так что в классе есть небольшие изменения.
На вопрос нах вообще нуже декоратор я отвечать не буду - читайте вики или еще что-то. А вот на вопрос как это работает отвечу. Для начала создадим класс который нужно декорировать.
class MyClass {
private $property;
public function __construct($property){
$this->property = $property;
}
public function printMethodName(){
echo __METHOD__;
}
public function printMyArgument($arg){
echo $arg;
}
public function printMyProperty(){
echo $this->property;
}
public function myDecoratedMethod(){
echo "Decorated Method!";
}
}
Как понятно методы особой смысловой нагрузки не несут, а только показывают что были вызваны именно они. Теперь создадим класс производный от декоратора, который будет декорировать последний метод класса MyClass.
class ConcreteDecorator extends Decorator {
public function myDecoratingMethod(){
return $this->myDecoratedMethod();
}
}
Теперь это все можно использовать примерно вот таким образом:
$myObj = new ConcreteDecorator("MyClass", array("String passed via constructor"));
$myObj->printMyProperty();
$myObj->printMethodName();
$myObj->printMyArgument("String passed via printMyArgument");
$myObj->myDecoratingMethod();
Но что-то как-то некрасиво получается, надо бы добавить в после каждого метода обрыв строки, для этого создадим еще один декоратор:
class MyNewLineDecorator extends Decorator {
public function __call($name,$args){
parent::__call($name,$args);
echo "<br />";
}
}
И добавим его в код.
$myObj = new ConcreteDecorator("MyClass", array("String passed via constructor"));
$myObj = new MyNewLineDecorator($myObj);
$myObj->printMyProperty();
$myObj->printMethodName();
$myObj->printMyArgument("String passed via printMyArgument");
$myObj->myDecoratingMethod();
В результате получаем:
String passed via constructor<br /> MyClass::printMethodName<br /> String passed via printMyArgument<br /> Decorated Method!<br />
Приятного использования.
ИМХО это из разряда "моя первая цмс"
посмотри на ДЛЕ 8.5 ...
это факт ..