Intereting Posts
Присоединиться к таблице в Symfony 2 org.json.JSONException: Значение <br типа java.lang.String не может быть преобразовано в JSONObject Использование пароля для существующего пароля Передать относительный путь в абсолютный URL с помощью PHP Как установить выбранное значение окна выбора HTML с помощью PHP Могу ли я создать приложение exe для Windows с помощью PHP-программы и с помощью базы данных? В чем разница между клиентским и серверным программированием? как хранить конфигурации для приложения php – xml или ini или db Возможно ли запускать .php-файлы на моем локальном компьютере? Как взять все слова в одном нормальном массиве из базы данных в рамках Laravel с минимальной потерей времени? Установить расширение fileinfo php Есть ли способ увидеть подготовленный запрос, поскольку он будет выполнен в базе данных? CSV без кавычек, не работающих с fgetcsv Я нарушаю любую «хорошую практику php» в следующем массиве php, который имеет дело с 3 (человеческими) языками? Настройка обратного прокси-сервера NGINX для веб-сайтов, размещенных на S3

Как реализовать декоратор в PHP?

Предположим, что существует класс, называемый « Class_A », он имеет функцию-член, называемую « func ».

Я хочу, чтобы « func » выполнял некоторую дополнительную работу, обернув Class_A классом декоратора.

 $worker = new Decorator(new Original()); 

Может ли кто-нибудь привести пример? Я никогда не использовал OO с PHP.

Правильно ли следующая версия?

 class Decorator { protected $jobs2do; public function __construct($string) { $this->jobs2do[] = $this->do; } public function do() { // ... } } 

Вышеупомянутый код намеревается добавить некоторую дополнительную работу в массив.

Solutions Collecting From Web of "Как реализовать декоратор в PHP?"

Я бы предположил, что вы также создаете унифицированный интерфейс (или даже абстрактный базовый класс) для декораторов и объектов, которые вы хотите украсить.

Чтобы продолжить приведенный выше пример, вы можете иметь что-то вроде:

 interface IDecoratedText { public function __toString(); } 

Затем, конечно, измените как Text и LeetText чтобы реализовать интерфейс.

 class Text implements IDecoratedText { ...//same implementation as above } class LeetText implements IDecoratedText { protected $text; public function __construct(IDecoratedText $text) { $this->text = $text; } public function __toString() { return str_replace(array('e', 'i', 'l', 't', 'o'), array(3, 1, 1, 7, 0), $this->text->toString()); } } 

Зачем использовать интерфейс?

Потому что тогда вы можете добавить столько декораторов, сколько хотите, и быть уверенным, что каждый декоратор (или объект, который будет оформлен) будет обладать всеми необходимыми функциями.

Это довольно легко, особенно на динамически типизированном языке, таком как PHP:

 class Text { protected $string; /** * @param string $string */ public function __construct($string) { $this->string = $string; } public function __toString() { return $this->string; } } class LeetText { protected $text; /** * @param Text $text A Text object. */ public function __construct($text) { $this->text = $text; } public function __toString() { return strtr($this->text->__toString(), 'eilto', '31170'); } } $text = new LeetText(new Text('Hello world')); echo $text; // H3110 w0r1d 

Вы можете также взглянуть на статью в Википедии .

Ни один из этих ответов не выполняет Decorator правильно и элегантно. Ответ mrmonkington близок, но вам не нужно использовать отражение, чтобы ввести шаблон Decorator в PHP. В другом потоке @Gordon показывает, как использовать декоратор для регистрации активности SOAP . Вот как он это делает:

 class SoapClientLogger { protected $soapClient; // this is standard. Use your constuctor to set up a reference to the decorated object. public function __construct(SoapClient $client) { $this->soapClient = $client; } ... overridden and / or new methods here ... // route all other method calls directly to soapClient public function __call($method, $args) { // you could also add method_exists check here return call_user_func_array(array($this->soapClient, $method), $args); } } 

И он – небольшая модификация, где вы можете передать желаемую функциональность конструктору:

 class Decorator { private $o; public function __construct($object, $function_name, $function) { $this->o = $object; $this->$function_name = $function; } public function __call($method, $args) { if (!method_exists($this->o, $method)) { throw new Exception("Undefined method $method attempt in the Url class here."); } return call_user_func_array(array($this->o, $method), $args); } } 

Я хотел использовать украшение, чтобы побудить коллег использовать кеширование больше, и вдохновил хороший синтаксис Python, экспериментированный с рефлексией PHP, чтобы подделать эту языковую функцию (и я должен подчеркнуть «подделку»). Это был полезный подход. Вот пример:

 class MrClass { /** * decoratorname-paramname: 50 * decoratorname-paramname2: 30 */ public function a_method( $args ) { // do some stuff } } class DecoratorClass { public function __construct( $obj ) { $this->obj = $obj; $this->refl = new ReflectionClass( $obj ); } public function __call( $name, $args ) { $method = $this->refl->getMethod( $name ); // get method's doccomment $com = trim( $method->getDocComment() ); // extract decorator params from $com $ret = call_user_func_array( array( $this->obj, $name), $args ); // perhaps modify $ret based on things found in $com return $ret; } 

Лучшие примеры с примерами кеширования: https://github.com/mrmonkington/EggCup/

Ключевой и уникальной особенностью Decorator является то, что один абстрактный класс расширяет другой. Участник Decorator является оберткой и расширяет компонент Component.

 <?php abstract class Decorator extends IComponent { //public function getDescription() { } } ?> 

Я считаю, что это единственный пример, когда это происходит в каталоге «Банда четырех». Декоратор позволяет легко добавлять свойства к объекту без изменения объекта. Для простого, точного и четкого примера см .:

http://www.php5dp.com/php-decorator-design-pattern-accessorizing-your-classes/#more-32