← Назад к вопросам

Что такое паттерн Publisher Subscriber?

2.3 Middle🔥 171 комментариев
#JavaScript Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Паттерн Publisher Subscriber

Паттерн Publisher-Subscriber (Издатель-Подписчик) — это архитектурный паттерн взаимодействия между компонентами, в котором один объект (издатель) отправляет сообщения, не зная напрямую, кто их будет получать. Вместо этого заинтересованные объекты (подписчики) явно подписываются на события издателя и реагируют на них.

Суть и основные концепции

Основная идея паттерна — разделение ответственности: издатель не нуждается в знании о подписчиках, а подписчики могут быть добавлены или удалены динамически. Это создает слабую связанность (loose coupling) между компонентами.

Ключевые элементы:

  • Publisher (Издатель) — объект, который генерирует события
  • Subscriber (Подписчик) — объект, который слушает и реагирует на события
  • Event (Событие) — данные, передаваемые от издателя к подписчикам
  • Event Channel (Канал событий) — механизм доставки событий

Пример реализации на JavaScript

// Простая реализация Event Emitter
class EventEmitter {
  constructor() {
    this.events = {};
  }

  subscribe(eventName, callback) {
    if (!this.events[eventName]) {
      this.events[eventName] = [];
    }
    this.events[eventName].push(callback);
    
    return () => {
      this.events[eventName] = this.events[eventName].filter(cb => cb !== callback);
    };
  }

  publish(eventName, data) {
    if (this.events[eventName]) {
      this.events[eventName].forEach(callback => {
        callback(data);
      });
    }
  }
}

const eventBus = new EventEmitter();

const publishUser = (userData) => {
  console.log('Пользователь создан:', userData);
  eventBus.publish('user:created', userData);
};

const unsubscribeLogger = eventBus.subscribe('user:created', (user) => {
  console.log('Логируем создание пользователя:', user.name);
});

const unsubscribeEmail = eventBus.subscribe('user:created', (user) => {
  console.log('Отправляем email на:', user.email);
});

publishUser({ id: 1, name: 'Иван', email: 'ivan@example.com' });

unsubscribeLogger();

Применение в React

В React паттерн Publisher-Subscriber часто реализуется через Context API и Custom Hooks:

import { createContext, useContext, useState, useCallback } from 'react';

const EventContext = createContext();

export function EventProvider({ children }) {
  const [events, setEvents] = useState({});

  const subscribe = useCallback((eventName, callback) => {
    setEvents(prev => ({
      ...prev,
      [eventName]: [...(prev[eventName] || []), callback]
    }));
    
    return () => {
      setEvents(prev => ({
        ...prev,
        [eventName]: prev[eventName].filter(cb => cb !== callback)
      }));
    };
  }, []);

  const publish = useCallback((eventName, data) => {
    setEvents(prev => {
      if (prev[eventName]) {
        prev[eventName].forEach(callback => callback(data));
      }
      return prev;
    });
  }, []);

  return (
    <EventContext.Provider value={{ subscribe, publish }}>
      {children}
    </EventContext.Provider>
  );
}

export const useEvents = () => useContext(EventContext);

Преимущества паттерна

  • Слабая связанность: компоненты не зависят друг от друга напрямую
  • Масштабируемость: легко добавлять новых подписчиков
  • Переиспользуемость: издатель не привязан к конкретным подписчикам
  • Асинхронность: события могут обрабатываться асинхронно

Недостатки

  • Сложность отладки: сложнее отследить поток данных
  • Производительность: много подписчиков замедляют выполнение
  • Утечки памяти: необходимо правильно отписываться от событий
  • Неявность зависимостей: непонятно, где и как используются события

Когда использовать

Паттерн Publisher-Subscriber полезен когда:

  • Нужна коммуникация между несвязанными компонентами
  • Количество подписчиков неизвестно на момент разработки
  • Требуется асинхронная обработка событий
  • Нужна высокая модульность приложения

Для Frontend разработчика это один из фундаментальных паттернов, лежащих в основе взаимодействия компонентов в современных приложениях.

Что такое паттерн Publisher Subscriber? | PrepBro