Pull to refresh

Observer vs Pub-Sub

Reading time4 min
Views63K
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
  • Примеры кода
Only registered users can participate in poll. Log in, please.
Observer отличается от Pub-sub?
61.55% Да325
6.44% Нет34
32.01% Это философский вопрос169
528 users voted. 87 users abstained.
Tags:
Hubs:
+10
Comments43

Articles

Change theme settings