Рубрики
Uncategorized

Шаблон дизайна PHP (8) декоратор иллюстратор шаблонов

Автор оригинала: David Wong.

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

1. Обзор

Если вы занимались объектно-ориентированной разработкой, вы можете добавить поведение в класс или объект и использовать механизм наследования. Это основная особенность всех объектно-ориентированных языков. Если в существующем классе отсутствуют некоторые методы или необходимо добавить дополнительные функции к методу, вы можете просто наследовать класс, чтобы создать новый класс на основе дополнительного кода.

Наследуя существующий класс, подкласс может иметь свои собственные методы, а также методы своего родительского класса. Но этот метод статичен, и пользователи не могут контролировать, как и когда увеличивать поведение. Если вы хотите изменить поведение инициализированного объекта, что вы делаете? Или, если вы хотите унаследовать поведение многих классов, что вы делаете? Первый из них может быть выполнен только во время выполнения. Последнее, очевидно, возможно, но это может привести к большому количеству различных классов – ужасных вещей.

2. Проблемы

Как вам легко организовать свои базовые классы без добавления дополнительных функций непосредственно в ваш код?

Решение 3

Шаблон декоратора: динамическое добавление дополнительных обязанностей или поведения к объекту. С точки зрения добавления функций шаблон декоратора более гибок, чем создание подклассов.

Шаблон декоратора обеспечивает гибкий способ изменения подклассов. Режим декоратора может динамически расширять функцию объекта без изменения исходного файла класса и использования наследования. Он обертывает реальный объект, создавая объект-оболочку или украшение.

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

4. Применимость

Шаблон декоратора используется в следующих случаях

1) Добавьте обязанности к отдельным объектам динамичным и прозрачным образом, не затрагивая другие объекты.

2) Разберитесь с обязанностями, которые могут быть сняты.

3) Когда метод генерации подкласса не может быть использован для расширения. В одном случае может быть много независимых расширений,

Для поддержки каждой комбинации будет сгенерировано большое количество подклассов, что приводит к взрывному росту числа подклассов.

Другая возможность заключается в том, что определение класса скрыто или не может быть использовано для создания подклассов.

5. Структура

UML показан следующим образом:

6. Состав режима строительства

Абстрактный компонент: Определите интерфейс объекта, чтобы указать объекты, готовые взять на себя дополнительные обязанности,

То есть вы можете динамически добавлять обязанности к этим объектам.

Конкретный компонент: Декоратор определяет класс, который будет оформлен для добавления функциональности.

Вы можете добавить некоторые обязанности к объектам этого класса

Декоратор: Поддерживайте экземпляр, указывающий на объект компонента,

И определите интерфейс, соответствующий интерфейсу компонента роли абстрактного компонента

Декоратор бетона: Добавьте обязанности к компоненту.

7. Эффект

Характеристики режима украшения следующие:

(1) декоративные объекты и реальные объекты имеют один и тот же интерфейс. Таким образом, клиентские объекты могут взаимодействовать с объектами декора так же, как и с реальными объектами. (2) объект украшения содержит индекс реального объекта (3) объект украшения принимает все запросы от клиента. Он пересылает эти запросы реальному объекту. (4) объекты оформления могут добавлять некоторые дополнительные функции до или после пересылки этих запросов. Это гарантирует, что дополнительные функции могут быть добавлены извне во время выполнения без изменения структуры данного объекта. В объектно-ориентированном дизайне наследование обычно используется для расширения функции данного класса.

Режим декоратора имеет по крайней мере два основных преимущества и два недостатка

1) Более гибкое, чем статическое наследование: по сравнению со статическим наследованием (множественное наследование) шаблон декоратора обеспечивает более гибкий способ добавления обязанностей к объектам. Вы можете добавлять и удалять обязанности во время выполнения, добавляя и разделяя их с помощью украшений. Напротив, механизм наследования требует, чтобы для каждой дополнительной ответственности создавался новый подкласс. Это приводит к появлению множества новых классов и увеличивает сложность системы. Кроме того, предоставление нескольких различных классов декораторов для определенного класса компонентов позволяет смешивать и сочетать некоторые обязанности. Используя шаблон декоратора, вы можете легко добавлять функцию повторно. 2) Чтобы избежать слишком большого количества характеристик классов в верхней части иерархии, шаблон декоратора обеспечивает оплату по мере того, как вы подходите к добавлению обязанностей. Вместо того, чтобы пытаться поддерживать все предсказуемые функции в сложном настраиваемом классе, вы можете определить простой класс и использовать класс декоратора для

8. Реализация

Используйте примеры в шаблонах проектирования PHP.

Взгляните на следующие примеры, чтобы лучше понять эту точку зрения. Рассмотрим библиотеку форм “форма”, основанную на концепции компонентов, где вам необходимо создать класс для каждого типа элемента управления формой, который вы хотите представить. Эта диаграмма классов может быть следующей:

Класс выбора и ввода текста является подклассом класса компонентов. Если вы хотите добавить “помеченный” компонент – форма ввода сообщит вам, что вводить. Поскольку может потребоваться пометить любую форму, вы можете наследовать каждый конкретный компонент следующим образом:

Приведенная выше диаграмма классов выглядит не так уж плохо. Давайте добавим еще несколько функций. На этапе проверки формы вы хотите иметь возможность указать, является ли элемент управления формой законным. Код, который вы используете для незаконного контроля, снова наследует другие компоненты, поэтому вам необходимо создать большое количество подклассов:

Этот класс выглядит не так уж плохо, поэтому давайте добавим некоторые новые функции. При проверке структуры необходимо указать, является ли структура допустимой. Вам нужен код, позволяющий проверить правильность применения к другим частям, чтобы вам не приходилось выполнять проверку на других подклассах.

Переполнение подкласса-не единственная проблема здесь. Подумайте о повторяющемся коде, который вам нужен для изменения всей иерархии классов. Нет лучшего способа! Действительно, режим декоратора-хороший способ избежать этого.

Шаблон декоратора по структуре похож на шаблон прокси. Объект декоратора сохраняет ссылку на объект и точно восстанавливает открытый интерфейс украшенного объекта. Декораторы также могут добавлять методы, расширять интерфейсы декорированных объектов, произвольно перегружать методы и даже условно перегружать методы во время выполнения скрипта.

Чтобы изучить шаблон декоратора, давайте возьмем в качестве примера библиотеку компонентов формы, рассмотренную ранее, и реализуем функции “метка” и “проверка” с шаблоном декоратора вместо наследования.

Пример кода:

Какие функции содержит библиотека компонентов?

1. Легко создавать элементы формы

2. Выведите элементы формы в виде HTML

3. Выполните простую проверку каждого элемента

В этом случае мы создаем форму, содержащую фамилию, имя, адрес электронной почты и ввод. Требуются все области, и электронная почта должна быть действительным адресом электронной почты. В HTML код формы выглядит следующим образом:

php" method="post"> First Name:
Last Name:
Email:

После добавления некоторых стилей CSS форма будет отображаться, как показано на следующем рисунке:

Мы используем код декоратора:

_asHtml();
 }
}
 
/**
 * 
 *Concrete component:
 *Let's start with a basic text input component. It must contain the name of the input field, and the input can be rendered in HTML.
 * 
 */
class ConcreteComponentTextInput extends ComponentWidget {
 
 protected $_name;
 protected $_value;
 
 function TextInput($name, $value='') {
 $this->_name = $name;
 $this->_value = $value;
 }
 
 function _asHtml() {
 return '';
 
 }
 
}
/**
 *Decorator: maintains an instance pointing to component object and defines an interface consistent with component interface of abstract component role.
 * 
 *We go into decorator mode that has the ability to add (some features) uniformly.
 *To start, we create a common widgetdecorator class that can be extended to produce specific decorators. At least the widgetdecorator class should be able to accept a component in its constructor,
 *And copy the public method paint ()
 *
 */
class WidgetDecorator {
 
 protected $_widget;
 function __construct( &$widget) {
 $this->_widget = $widget;
 }
 function paint() {
 return $this->_widget->paint();
 
 }
 
}
/**
 *Concrete decorator:
 *To create a label, you need to pass in the content of the label and the original components
 *Labeled components also need to copy the paint () method
 *
 */
 
class ConcreteDecoratorLabeled extends WidgetDecorator {
 
 protected $_label;
 
 function __construct($label, &$widget) {
 $this->_label = $label;
 parent::__construct($widget);
 }
 
 function paint() {
 return ''.$this->_label.': '.$this->_widget->paint();
 }
 
}
 
/**
 *Implementation
 *
 */
class FormHandler {
 function build(&$post) {
 return array(
 new ConcreteDecoratorLabeled('First Name', new ConcreteComponentTextInput('fname', $post->get('fname')))
 ,new ConcreteDecoratorLabeled('Last Name', new ConcreteComponentTextInput('lname', $post->get('lname')))
 ,new ConcreteDecoratorLabeled('Email', new ConcreteComponentTextInput('email', $post->get('email')))
 );
 
 }
 
}
 
/**
 *Through$_ Data submitted by post
 */
 
class Post {
 
 private $store = array();
 
 function get($key) {
 if (array_key_exists($key, $this->store))
 return $this->store[$key];
 }
 
 function set($key, $val) {
 $this->store[$key] = $val;
 }
 
 static function autoFill() {
 $ret = new self();
 foreach($_POST as $key => $value) {
  $ret->set($key, $value);
 }
 return $ret;
 }
 
}
?>

Чтобы создать PHP-скрипт, используйте класс formhandler для создания HTML-форм

paint(), "
\n"; } ?>

Теперь у вас есть класс обработчика форм, который отправляет сам себе и хранит опубликованные данные. Сейчас? Мы продолжаем добавлять некоторые механизмы проверки в форму. Метод состоит в том, чтобы отредактировать другой класс декоратора компонентов, чтобы выразить “недопустимое” состояние, и расширить класс formhandler, добавив метод validate () для обработки массива образцов компонентов. Если компонент является незаконным (“недопустимым”), мы помещаем его в элемент < span > через “недопустимый” класс.

widget->paint().'';
 }
}

Новый метод обработчика форм: проверка:

/**
 *Implementation
 *
 */
class FormHandler {
 function build(&$post) {
 return array(
 new ConcreteDecoratorLabeled('First Name', new ConcreteComponentTextInput('fname', $post->get('fname')))
 ,new ConcreteDecoratorLabeled('Last Name', new ConcreteComponentTextInput('lname', $post->get('lname')))
 ,new ConcreteDecoratorLabeled('Email', new ConcreteComponentTextInput('email', $post->get('email')))
 );
 
 }
 
 function validate(&$form, &$post) {
 $valid = true;
 // first name required
 if (!strlen($post->get('fname'))) {
  $form[0] =& new Invalid($form[0]);
  $valid = false;
 }
 
 // last name required
 if (!strlen($post->get('lname'))) {
  $form[1] =& new Invalid($form[1]);
  $valid = false;}
  // email has to look real
  if (!preg_match('~\[email protected](\w+\.)+\w+~'
  ,$post->get('email'))) {
  $form[2] =& new Invalid($form[2]);
  $valid = false;
  }
  return $valid;
 
 }
}

Окончательные результаты были следующими



Decorator Example



" method="post">
paint(), "
\n"; } ?>

9. Режим декоратора и другие связанные с ним режимы

1) Шаблон адаптера: шаблон декоратора отличается от шаблона адаптера, поскольку оформление изменяет только ответственность объектов, оно не изменяет его интерфейс; вместо этого адаптер предоставляет объекту совершенно новый интерфейс.

2) Композитный узор: вы можете рассматривать украшение как вырожденную группу из одного компонента Вместе. Украшение, однако, только добавляет некоторую дополнительную ответственность объекту – оно не предназначено для объединения объектов.

3) Режим стратегии: вы можете изменить внешний вид объекта с помощью украшения; режим стратегии позволяет изменить ядро объекта. Это два способа изменить объект.

10. Краткое изложение

1) Он основан на существующем шаблоне проектирования объекта, который не требует использования каких-либо изменений объектного кода.

2) Шаблон дизайна декоратора построен таким образом, что один или несколько декораторов, которые изменяют или “украшают” целевой объект, могут быть непосредственно вставлены в основной поток кода,

В то же время это не влияет на другие потоки кода.

3) Шаблон декоратора использует метод композиции объектов вместо наследования, чтобы реализовать возможность динамического расширения функций объекта во время выполнения,

Кроме того, он может расширять несколько функций по мере необходимости, избегая “плохой гибкости” и “многоклассового вывода”, вызванного только использованием наследования.

В то же время это соответствует принципам объектно-ориентированного проектирования, таким как “приоритет композиции объекта, а не наследования” и “открыть закрыть”.

Возможно, самым важным аспектом шаблона декоратора является его способность выходить за рамки наследования. В разделе “проблемы” показано множество подклассов, использующих наследование.

На основе решения шаблона декоратора диаграмма классов UML показывает это простое и гибкое решение.

Подробнее о содержании, связанном с PHP заинтересованные читатели могут ознакомиться с этой темой сайта: “Вводный учебник по объектно-ориентированному программированию PHP”, “Навыки работы с массивом PHP (массив)”, “Вводный курс по основному синтаксису PHP”, “Краткое описание операций PHP и использования операторов”, “Краткое описание использования символьной строки (строки) PHP”, “Руководство по вводу в работу с базой данных PHP + MySQL” и “Общая работа с базой данных PHP” Краткое описание навыков написания

Я надеюсь, что эта статья поможет вам в программировании на PHP.