Это пост # 47 из серии, посвященный изучению JavaScript и его компонентов. В процессе определения и описания основных элементов мы также делимся некоторыми практическими правилами, которые мы используем при создании SessionStack, приложения JavaScript, которое должно быть надежным и высокопроизводительным, чтобы помочь компаниям оптимизировать цифровой опыт своих пользователей.
Введение
Возможность идентифицировать повторяющиеся шаблоны или темы в нашем коде является важным требованием для его оптимизации. И здесь понимание паттернов проектирования неоценимо.
Шаблоны проектирования - это многократно используемые решения общих проблем проектирования программного обеспечения.
Важно отметить, что шаблоны проектирования сами по себе не являются законченными решениями, но они предоставляют нам схему решения. Мы можем думать о них как о шаблонах для решения проблем проектирования программного обеспечения.
Шаблоны проектирования дают нам проверенные подходы к общим проблемам разработки программного обеспечения, и, поскольку они не зависят от языка, они могут использоваться и повторно использоваться кем угодно с любым языком.
Хотя они отражают опыт разработчиков, которые их определили, они являются расширяемыми. Таким образом, другие разработчики могут адаптировать их под свои нужды.
Концепция шаблона проектирования давно присутствует в программировании, но в менее формальной форме. Однако в 1995 году группа, широко известная как банда четырех или GoF, опубликовала свою книгу Шаблоны проектирования: элементы многоразового объектно-ориентированного программного обеспечения.
Эта публикация GoF способствовала росту популярности шаблонов проектирования в разработке программного обеспечения, и на сегодняшний день она часто считается самой знаковой публикацией шаблонов проектирования.
В своей книге они представили двадцать три объектно-ориентированных шаблона, которые используются на сегодняшний день, а также ряд методов и ошибок разработки программного обеспечения.
Вы можете узнать больше об этих шаблонах и о том, зачем они нужны, в предыдущей статье, в которой говорилось о шаблонах проектирования в более общем плане.
В этой статье мы сосредоточимся на модели "издатель-подписчик". Давайте начнем с обзора в следующем разделе.
Образец наблюдателя
Шаблон наблюдателя - это шаблон проектирования, в котором вы определяете отношение «один ко многим» от одного объекта, известного как субъект, ко многим другим объектам, известным как наблюдатели.
Эти наблюдатели могут быть функциями, которые следят за субъектом и ждут сигнала или уведомления от субъекта перед запуском.
В шаблоне наблюдателя при изменении объекта он уведомляет зависимые объекты о том, что в его состоянии произошли изменения. Примером может служить архитектура модель-представление-контроллер. Когда вид обновляется, модель меняется.
Обработчики событий - еще один пример шаблона наблюдателя. Обработчики событий - это функции, которые прослушивают определенное событие и запускаются только при запуске этого события.
Шаблон наблюдателя состоит из объекта, который отслеживает всех наблюдателей, которые в настоящее время на него подписаны. Тема также содержит методы, которые упрощают добавление, удаление и уведомление этих зависимых объектов.
Ниже представлена простая реализация паттерна наблюдателя:
В приведенном выше коде конструктор Subject
поддерживает список наблюдателей. И мы добавили соответствующие методы в прототип Subject
. Это позволяет нам использовать эти методы для каждого экземпляра Subject
.
Если вы не понимаете, как мы можем совместно использовать методы, используя прототип объекта, я предлагаю вам прочитать предыдущую статью, посвященную прототипному наследованию в JavaScript.
В приведенном выше коде метод subscribe
добавляет наблюдателей в массив observers
, а метод unsubscribe
удаляет наблюдателей из массива observers
. Метод notify
будет уведомлять указанного подписанного наблюдателя, а метод notifyAll
уведомляет всех подписанных наблюдателей.
В шаблоне наблюдателя каждый наблюдатель должен подписаться на объект, запускающий событие - субъект, прежде чем он сможет получить уведомление. Однако шаблон pub / sub этого не требует. В шаблоне pub / sub используется промежуточное программное обеспечение, которое находится между объектами, запускающими событие. В этом случае издатели и подписанные объекты или подписчики. Давайте углубимся в шаблон дизайна pub / sub в следующем разделе.
Подробное описание модели "издатель-подписчик"
Шаблон pub / sub включает промежуточное программное обеспечение, которое также называется брокером pub / sub. Брокер pub / sub обрабатывает взаимодействие между издателями и подписчиками. Издатели публикуют контент или публикации для брокера публикации / подписки, и он обрабатывает доставку этого контента соответствующему подписчику.
Брокер pub / sub также обеспечивает свободное разделение издателей и подписчиков и поддерживает отношения от многих до многих между издателями и подписчиками.
Итак, в отличие от шаблона наблюдателя, шаблон pub / sub допускает использование нескольких издателей и нескольких подписчиков.
В шаблоне публикация / подписка издатель публикует содержимое в теме, и заинтересованные подписчики получают доступ к этому содержимому, отправляя подписки брокеру публикации / подписки для подписки на эту тему. Кроме того, в отличие от шаблона наблюдателя, и издателям, и подписчикам не нужно знать друг о друге.
Рассмотрим изображение ниже:
Существует множество реализаций шаблонов pub / sub, некоторыми примерами являются IBM Websphere MQ, RabbitMQ и RocketMQ, Apache Kafka, Google Cloud Pub / Sub и Pushy.
В этой статье мы реализуем базовую систему с использованием JavaScript.
Язык JavaScript хорошо подходит для шаблона pub / sub, потому что по своей сути большинство реализаций ECMAScript управляются событиями.
Наша реализация pub / sub состоит из pub / sub class
, который содержит массив событий, который используется для поддержки списка всех опубликованных событий.
Кроме того, pub / sub class
имеет метод subscription
, который обрабатывает все взаимодействия между издателями и подписчиками.
Давайте посмотрим на реализацию ниже:
В нашем небольшом примере выше метод subscription
возвращает объект, содержащий метод subscribe
, используемый для обработки подписок, и метод unsubscribe
, который обрабатывает отмены подписки.
Наконец, наш pub / sub class
содержит метод publish
, который принимает переменное количество аргументов и вызывает все функции, которые подписаны на указанное событие с этими аргументами, используя apply
. Вы можете узнать больше о том, как apply
работает, прочитав предыдущую статью из этой серии.
Преимущества шаблона публикации / подписки
Слабое разделение шаблона Pub / sub делает его пригодным для решения многих задач разработки программного обеспечения. Он хорошо масштабируется и хорошо подходит для распределенных архитектур, таких как микросервисы.
Pub / sub отлично подходит для создания уведомлений о событиях, распределенного кэширования, распределенного ведения журналов и систем с несколькими источниками данных.
Некоторые примеры реальных приложений, использующих шаблон pub / sub, - это Redis, Split, Twillo и Gutenberg, созданные Netflix.
Шаблон публикации / подписки против шаблона наблюдателя и привязки данных
Выше мы узнали, что основное различие между шаблоном pub / sub и наблюдателем заключается в том, что шаблон pub / sub предлагает полное отделение подписчиков от издателей. Однако в шаблоне наблюдателя наблюдатели или подписчики должны знать о предмете, также известном как наблюдаемые.
Кроме того, в шаблоне наблюдателя нет брокера, и наблюдаемые объекты сами отправляют уведомления.
Связывание данных - это общий термин. Вкратце, это просто означает, что «значение свойства X
объекта Foo
семантически привязано к значению свойства Y
объекта Bar
. Нет никаких предположений о том, как Foo
узнает или получает изменения на объекте Bar
.
Связывание данных может быть реализовано с использованием шаблона pub / sub или наблюдателя. И данные - это Publisher / Observable.
Заключение
Паттерны pub / sub и наблюдатель - это паттерны проектирования, с которыми должен быть знаком каждый разработчик.
Они побуждают нас серьезно задуматься о взаимоотношениях между различными компонентами нашего приложения. И они помогают нам организовать компоненты нашего приложения в более мелкие, слабо связанные блоки, которые легче поддерживать и повторно использовать.
SessionStack использует службы pub / sub для обработки всех полученных поведенческих данных из браузера в режиме реального времени. Во время приема данных SessionStack позволяет вам просматривать пользовательские сеансы в виде видео, позволяя точно увидеть, что произошло во время их путешествия.
Объединяя эту визуальную информацию со всеми техническими данными из браузера, такими как ошибки, трассировки стека, сетевые проблемы, данные отладки и т. д., вы можете легко понять проблемные области в вашем продукте и эффективно их решить.
Существует бесплатная пробная версия, если вы хотите попробовать SessionStack.
Если вы пропустили предыдущие главы серии, вы можете найти их здесь:
- Обзор движка, среды выполнения и стека вызовов
- Внутри движка Google V8 + 5 советов по написанию оптимизированного кода
- Управление памятью + как справиться с 4 распространенными утечками памяти
- Цикл событий и рост асинхронного программирования + 5 способов улучшить кодирование с помощью async / await
- Глубокое погружение в WebSockets и HTTP / 2 с SSE + как выбрать правильный путь
- Сравнение с WebAssembly +, почему в некоторых случаях лучше использовать его поверх JavaScript
- Строительные блоки Web Workers + 5 случаев, когда вы должны их использовать
- Сервис-воркеры, их жизненный цикл и сценарий использования
- Механика Web Push-уведомлений
- Отслеживание изменений в DOM с помощью MutationObserver
- Механизм рендеринга и советы по оптимизации его производительности
- Внутри сетевого уровня + как оптимизировать его производительность и безопасность
- Под капотом CSS и JS анимаций + как оптимизировать их производительность
- Синтаксический анализ, абстрактные синтаксические деревья (AST) + 5 советов, как минимизировать время синтаксического анализа
- Внутреннее устройство классов и наследование + транспиляция в Babel и TypeScript
- Механизмы хранения + как выбрать подходящий API хранилища
- Внутреннее устройство Shadow DOM + как создавать автономные компоненты
- WebRTC и механизм одноранговой связи
- Под капотом пользовательских элементов + Лучшие практики по созданию компонентов многократного использования
- Исключения + лучшие практики для синхронного и асинхронного кода
- 5 видов XSS-атак + советы по их предотвращению
- CSRF атаки + 7 стратегий смягчения
- Итераторы + советы по расширенному управлению генераторами
- Криптография + как бороться с атаками типа« злоумышленник посередине (MITM)»
- Функциональный стиль и его сравнение с другими подходами
- Три типа полиморфизма
- Регулярные выражения (RegExp)
- Введение в Deno
- Шаблоны творческого, структурного и поведенческого проектирования + 4 передовых практики
- Модульность и возможность многократного использования с MVC
- Кроссбраузерное тестирование + советы для предварительных версий браузеров
- Переменная« это и контекст выполнения»
- Высокопроизводительный код + 8 советов по оптимизации
- Обзор отладки + 4 совета по асинхронному коду
- Подробнее о вызове, применении и привязке
- Эволюция графики
- Докеризация приложения Node.js
- Глубокое погружение в декораторов
- Лучшие практики обеспечения соответствия данных
- Прокси и отражение
- SVG и варианты его использования (часть 1)
- Статические блоки класса + 6 предлагаемых семантик
- Введение в графики и деревья
- Введение в PM2, Strongloop и Forever + 4 совета для менеджеров производственных процессов
- Расширенные возможности SVG (часть 2)