Для тех, кто имеет обширный опыт в разработке программного обеспечения, шаблоны проектирования должны быть знакомой территорией; однако есть целая группа разработчиков — особенно в сообществе веб-разработчиков — которые не обязательно знакомы с шаблонами проектирования (даже если они, вероятно, использовали их!).
В этой серии мы рассмотрим шаблоны проектирования, особенно в контексте WordPress, их полезность и некоторые практические примеры, которые мы можем использовать в наших темах и плагинах.
Конечная цель серии — дать четкое определение того, что такое шаблоны проектирования, почему они полезны, как они используются в ядре WordPress, а затем рассмотреть два популярных примера, которые мы можем легко использовать в нашей собственной работе.
Прежде чем мы рассмотрим некоторые практические примеры, давайте определим шаблоны проектирования и рассмотрим пример их использования в ядре WordPress.
Шаблоны дизайна определены
Для тех из вас, кто никогда не слышал или никогда не использовал шаблоны проектирования, важно понять, что они из себя представляют, прежде чем мы действительно начнем использовать их в нашей работе.
Википедия дает следующее определение :
Шаблон проектирования в архитектуре и информатике — это формальный способ документирования решения проблемы проектирования в конкретной области знаний. Организованная коллекция шаблонов проектирования, которые относятся к определенному полю, называется языком шаблонов.
Возможно, более упрощенное определение будет:
Шаблон — это дизайн, который можно применить к проблеме в конкретной ситуации.
Если это все еще не ясно, подумайте об этом так:
- Всякий раз, когда вы создаете часть программного обеспечения, вы, вероятно, признаете, что решаете проблему, которую уже решили ранее. Таким образом, вы знаете, как решить эту проблему.
- Естественно, решением проблемы будет несколько более обобщенная форма, которая применима к тому, как вы применяли ее ранее.
- Эту обобщенную форму решения можно считать шаблоном проектирования.
Общая реализация и архитектура будут выглядеть точно так же; тем не менее, особенности реализации будут варьироваться от проекта к проекту, но это просто природа зверя.
В следующих разделах и будущих статьях мы рассмотрим это более подробно.
Шаблоны проектирования в WordPress
Если вы выполнили какой-либо тип разработки WordPress с использованием системы ловушек — то есть вы написали целые плагины, темы или даже простую функцию и воспользовались функциями add_action
или add_filter
— тогда вы использовали шаблоны проектирования.
WordPress использует так называемый шаблон проектирования, управляемый событиями. Существует несколько вариантов шаблонов проектирования, управляемых событиями, один из которых мы кратко рассмотрим, но суть шаблонов одинакова:
- Часть шаблона реализует то, что известно как издатель
- Часть шаблона реализует то, что известно как подписчик
Вообще говоря, издатель передает сообщение о том, что что- то случилось со всеми объектами, которые подписаны на этого конкретного издателя.
Другой способ взглянуть на это заключается в том, что в программном обеспечении всякий раз, когда что-то происходит, мы говорим, что происходит событие. Возможно, наиболее распространенное место, которое мы видим в веб-разработке, — это JavaScript с такими вещами, как нажатие мыши, нажатие клавиши на клавиатуре или что-то подобное.
Затем мы пишем функции, которые обрабатывают эти функции, и эти функции соответствующим образом называются обработчиками событий, потому что они отвечают за обработку случая, когда происходит событие.
Не очень сложно, правда? Честно говоря, иногда я думаю, что терминология может быть более запутанной, чем фактическая реализация.
Так или иначе, в контексте WordPress — или любого другого веб-приложения — события не ограничиваются нажатием клавиш или щелчками мыши. Вместо этого это может происходить во время различных частей жизненного цикла загрузки страницы, когда данные записываются в базу данных, когда данные считываются в базу данных и т. Д.
В конечном счете, вы можете реализовать шаблон так, как вам нравится, чтобы вы могли предоставить хуки, в которых разработчики могут регистрировать функции для запуска, как только происходит событие.
Это возвращает нас назад к архитектуре WordPress: хуки размещаются по всему коду так, что мы можем зарегистрировать функцию, которая будет запускаться всякий раз, когда что-то происходит (то есть, когда происходит событие).
Взгляд на управляемую событиями архитектуру: шаблон наблюдателя
Существует несколько шаблонов проектирования, управляемых событиями, один из которых известен как Шаблон наблюдателя. Этот конкретный шаблон также известен как шаблон издатель-подписчик или, точнее, Pub-Sub.
В простейшей реализации этого шаблона существует один издатель, который отвечает за рассылку сообщений одному или нескольким подписчикам. Подписчики несут ответственность за регистрацию себя у издателя, а затем издатель отвечает за отправку сообщения или выполнение действий со всеми подписчиками.
Диаграмма высокого уровня будет выглядеть примерно так:
С точки зрения кода, издателю нужны три вещи:
- Способ ведения списка подписчиков
- Способ для подписчиков зарегистрироваться
- Способ передать сообщение всем подписчикам
Аналогично, подписчик должен уметь делать две вещи:
- Зарегистрируйтесь в издательстве
- При необходимости принять меры, когда издатель отправляет ему сообщение
Есть несколько способов, которыми это может быть реализовано, но для всех намерений и целей и для того, чтобы пример был относительно простым, допустим, что подписчики зарегистрируются в издателе с помощью метода register
Observer, и функция принимает ссылку на у подписчика и у каждого подписчика есть метод update
который издатель вызывает при рассылке сообщения.
Код издателя
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
class MyPublisher {
/** The list of subscribers that are registered with this publisher */
private $subscribers;
/**
* Responsible for initializing the class and setting up the list of subscribers.
*/
public function __construct() {
$this->subscribers = array();
} // end constructor
/**
* Adds the incoming subject to the list of registered subscribers
*
* @param array $subject The subject to add to the list of subscribers
*/
public function register( $subject ) {
array_push( $this->subscribers, $subject );
} // end register_subscriber
/**
* Notifies all of the subscribers that something has happened by calling their `update`
* method.
*/
public function notify_subscribers() {
for ( $i = 0; $l < count( $this->subscribers ); $i++ ) {
$current_subscriber = $this->subscribers[ $i ];
$current_subscriber->update();
} // end for
} // end notify_subscribers
} // end class
|
Код выше настолько прост, насколько мы можем сделать это:
Для тех, кто более опытен в объектно-ориентированных методах, вы, вероятно, увидите необходимость создания интерфейса класса для издателя, но это выходит за рамки этого конкретного руководства.
Помните, цель состоит в том, чтобы просто предоставить пример того, как может выглядеть простой наблюдатель.
Код подписки
Создание издателя — это только половина реализации. Помните, у нас должно быть что-то, что на самом деле, вы знаете, подписывается на издателя, чтобы действовать, когда что-то происходит.
Это где точно названный подписчик вступает в игру.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
class MySubscriber {
/** The publisher to which this class registers */
private $publisher;
/**
* Responsible for initializing the class and setting up a reference to the publisher
*/
public function __construct() {
$this->publisher = new MyPublisher();
$this->publisher->register( $this );
} // end constructor
/**
* This is the method that the Publisher calls when it it broadcasts its message.
*/
public function update() {
/** Implementation is based purely on however you’d like.
} // end update
} // end class
|
Короче, это так. Обратите внимание, что эта реализация функции update
самом деле не определена. Это потому, что это дает нам возможность обеспечить уникальное поведение для этого конкретного экземпляра.
Но помните, что в ядре WordPress много кода, который не является объектно-ориентированным. Вместо этого это процедурный. Таким образом, реализация такого шаблона немного отличается.
Например, аналогия в WordPress будет выглядеть примерно так:
1
2
3
4
5
6
7
|
function my_custom_subscriber( $content ) {
$content = ‘This is my custom content.’
return $content;
} // end my_custom_subscriber
add_action( ‘the_content’, ‘my_custom_subscriber’ );
|
Обратите внимание, что синтаксис немного отличается, но мы, по сути, делаем очень похожую вещь:
- У нас есть функция подписки —
my_custom_subscriber
— и она зарегистрирована в событииthe_content
- Когда
the_content
функцияthe_content
наша пользовательская функция.
Надеюсь, ничего сложного.
Одна из целей этой серии — не только предоставить несколько примеров шаблонов проектирования и способов их реализации, но они уже существуют в существующих системах.
Шаблоны, которые мы рассмотрим
В дополнение к шаблону, управляемому событиями, который мы рассмотрели выше, мы также рассмотрим два шаблона, которые являются общими, практичными и чрезвычайно полезными в нашей повседневной работе.
В частности, мы рассмотрим следующие шаблоны:
- Синглтон В объектно-ориентированном проектировании единый шаблон обеспечивает создание только одного экземпляра класса. Это полезно для того, чтобы мы случайно не создали несколько экземпляров, поддерживающих свои собственные наборы данных, что в конечном итоге дает противоречивые результаты в течение жизненного цикла проекта.
- Простая фабричная модель . Если у вас есть коллекция классов, каждый из которых предназначен для обработки определенного типа данных (в отличие от того, чтобы это делал один большой класс), тогда Simple Factory Pattern будет полезен для просмотра входящих данных и последующего возврата экземпляр правильного класса для обработки данных.
Очевидно, что разговор о программном обеспечении заходит так далеко, не говоря уже о диаграммах и / или коде, поэтому мы рассмотрим оба из них в следующем наборе статей.
Вывод
Как вы можете видеть, концепция шаблонов проектирования не является чем-то ужасно сложным, и их использование в нашей работе дает много нового. Пожалуй, самая большая проблема, с которой сталкиваются разработчики, заключается в использовании шаблонов проектирования ради использования шаблонов проектирования.
Вместо этого важно понимать, что существуют определенные ситуации, в которых применимы шаблоны проектирования. То есть существуют определенные проблемы, для которых шаблоны проектирования являются идеальным решением. Возможно, опыт — лучший учитель, который знает, когда использовать шаблон проектирования, а когда — нет.
В следующих статьях, мы надеемся, мы сможем охватить достаточно территории, чтобы предоставить два убедительных примера шаблонов проектирования, когда они применимы, как их использовать и как они могут помочь нам в нашей будущей работе.