Observer и Pub-sub, наверное самые известные паттерны взаимодействия в мире разработки интерфейсов и JavaScript. Но несмотря на свою известность, некоторые разработчики считают эти паттерны одинаковыми, что и послужило подспорьем написать данную статью.





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

Но в мире интерфейсов и асинхронного JavaScript не возможно прожить без знания паттернов observer и pub-sub, так как знание и понимание этих шаблонов, значительно облегчает жизнь разработчику.

Observer и Pub-sub относятся к поведенческим паттернам (паттернам взаимодействия), т.е. применяются, когда требуется организовать взаимодействие между различными объектами системы.

Observer


Observer представляет собой не что иное, как связь один-ко-многим. В упрощенном виде этот паттерн состоит из объекта наблюдения (subject) и наблюдателей (observers).

Принципиальная схема взаимодействия выглядит так:

Subject — реализует методы: observe, detach, notify, get, set.

Observer — реализует метод update.

Также subject содержит ссылки на всех observers, которые его слушают, а observer, в свою очередь содержит ссылку, на subject, на который он подписан.

Таким образом в этом паттерне наблюдается прямая связь между объектами, т.е. subject знает о всех своих observers и вручную оповещает их о происходящих в себе изменениях, вызывая метод update у каждого observer. Связь устанавливается методом observe, разрывается методом detach.

Subject хранит внутри себя свое состояние и все действия с его состоянием необходимо совершать используя get/set методы, чтобы при изменениях состояния вызывать метод notify. Подобная схема реализована в EmberJs.

Observer можно представить довольно неплохой картинкой (заимствовано тут):

Примерную реализацию можно найти на сайте Addy Osmani.

Pub-sub



Pub-sub паттерн является одной из вариаций паттерна Observer. Исходя из названия в паттерне выделяют два компонента Publisher (издатель) и Subscriber (подписчик). В отличие от Observer, связь между объектами осуществляется посредством канала связи Event Channel (шины событий).

Publisher кидает свои события в Event Channel, а Subscriber подписывается на нужное событие и слушает его на шине, что обеспечивает отсутствие прямой связи между подписчиком и издателем.

Схематично Pub-sub и отличие от Observer, можно представить так:


Таким образом можно выделить основные отличительные особенности между Pub-sub и Observer:
  1. отсутствие прямой связи между объектами
  2. объекты сигнализируют друг другу событиями, а не состояниями объекта
  3. возможность подписываться на различные события на одном объекте с различными обработчиками


Одной из наиболее известных реализаций паттерна pub-sub является Backbone, AmplifyJs и др. DOM, в некоторой степени тоже реализует модель pub-sub.

Mediator



На основе pub-sub строится работа паттерна Mediator, который позволяет наладить коммуникацию между различными компонентами системы. Mediator представляет собой глобальный объект в системе, о котором знают все компоненты системы, при этом компонент может выступать как слушателем события, так и издателем другого события, таким образом налаживая коммуникацию между объектами системы.

Если провести аналогию, то Mediator это городская АТС, в которую приходят входящие и исходящие вызовы от абонентов, а доходят они строго до нужного абонента. Но как мы знаем у телефонной сети есть недостаток — на новый год она может оказаться перегруженной огромным количеством звонков и перестать доставлять вызова абонентам. Тоже самое может произойти и с Mediator, когда он не справится с потоком событий.

Mediator особенно полезен в тех случаях, когда наблюдаются множественные однонаправленные или двунаправленные связи между различными компонентами системы. Особенно паттерн полезен, когда в приложении имеются вложенные друг в друга компоненты системы (например, дочерние композиционные элементы), чтобы не было необходимости пробрасывать callbacks используя модель всплытия события изнутри наружу. Достаточно предоставить Mediator внутреннему компоненту, который опубликует свое событие, а другие компоненты узнают об этом событии.

Mediator паттерн довольно успешно реализован в Backbone — сам глобальный объект Backbone можно использовать в качестве Mediator, либо унаследоваться от Backbone.Events.

Что? Где? Когда?



Когда и где следует применять каждый паттерн — дело каждого, но прежде чем применять, следует понять их отличия и особенности. Например, Observer паттерн представляет собой прямую связь между объектами и сигнализирует наблюдателю об изменении своего состояния. На мой взгляд, данный паттерн очень хорошо подходит при разработке различных форм с множеством полей ввода, когда необходимо реагировать на изменения значений полей формы (binding).

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

Почитать


  • Learning Javascript Design Patters, Addy Osmani
  • Programming in the large with Design Patterns, Eddie Burris
  • Примеры кода
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Observer отличается от Pub-sub?
62.09%Да339
6.23%Нет34
31.68%Это философский вопрос173
Проголосовали 546 пользователей. Воздержались 88 пользователей.