Observer-паттерн

Observer-паттерн — это поведенческий шаблон проектирования, позволяющий объекту (наблюдаемому) уведомлять множество других объектов (наблюдателей) о произошедших изменениях состояния. В контексте Bliss.js этот паттерн реализуется через событийную систему, предоставляя лёгкий и эффективный способ организации взаимодействия между компонентами.

Bliss.js интегрирует Observer-подход в ядро своей работы с DOM, позволяя отслеживать изменения элементов, данных и пользовательских событий без явного связывания компонентов.


Подписка и уведомление

В Bliss.js объект может стать наблюдаемым с помощью метода observe. Подписка осуществляется через функцию, которая будет вызвана при изменении состояния.

let state = Bliss.observe({ count: 0 });

state.subscribe(({ count }) => {
    console.log('Текущее значение count:', count);
});

state.count = 1; // вызовет подписанную функцию и выведет: Текущее значение count: 1

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

  • observe(obj) — превращает объект в наблюдаемый.
  • subscribe(callback) — добавляет функцию-наблюдатель.
  • Любое изменение свойства объекта автоматически вызывает уведомление всех подписчиков.

Работа с вложенными объектами

Bliss.js поддерживает глубокое отслеживание изменений, включая вложенные структуры.

let data = Bliss.observe({
    user: { name: 'Alice', age: 25 }
});

data.subscribe(change => {
    console.log('Изменение:', change);
});

data.user.age = 26; 
// Изменение: { path: ['user','age'], oldValue: 25, newValue: 26 }

Особенности:

  • path показывает путь до изменённого свойства.
  • oldValue и newValue позволяют эффективно реагировать на изменения.
  • Вложенные объекты автоматически становятся наблюдаемыми при создании через observe.

Отписка от изменений

Для управления жизненным циклом наблюдателей используется метод unsubscribe.

let observer = state.subscribe(({ count }) => console.log(count));
state.count = 2; // вывод: 2

state.unsubscribe(observer);
state.count = 3; // вывод отсутствует
  • Подписчик сохраняется в переменной для возможности последующего удаления.
  • После отписки изменения больше не будут отслеживаться.

Группировка наблюдателей и фильтрация

Bliss.js позволяет организовать наблюдателей по событиям и фильтрам:

let tasks = Bliss.observe({
    list: []
});

tasks.subscribe(({ path, newValue }) => {
    if(path[0] === 'list' && newValue.length > 0){
        console.log('Добавлен новый элемент в список');
    }
});

tasks.list.push('Новая задача'); 
  • path помогает отследить, какое свойство объекта изменилось.
  • Можно фильтровать изменения и реагировать только на нужные.

Асинхронные изменения и batched updates

Bliss.js оптимизирует производительность при массовых изменениях:

Bliss.batch(() => {
    state.count = 10;
    state.count = 11;
});
  • Внутри batch все изменения группируются и уведомление подписчиков вызывается один раз.
  • Это снижает количество рендеров и улучшает производительность при работе с большими данными.

Примеры практического применения

UI-компоненты: автоматическое обновление интерфейса при изменении состояния:

let uiState = Bliss.observe({ visible: false });

uiState.subscribe(({ visible }) => {
    document.querySelector('#modal').style.display = visible ? 'block' : 'none';
});

uiState.visible = true; // Модальное окно появляется

Работа с формами: синхронизация данных формы с объектом:

let formData = Bliss.observe({ email: '', password: '' });

formData.subscribe(change => {
    console.log('Изменение формы:', change);
});

document.querySelector('#email').addEventListener('input', e => formData.email = e.target.value);
  • Observer-паттерн обеспечивает двустороннюю связь между состоянием и DOM без сложной логики.

Взаимодействие с другими паттернами

Observer легко сочетается с паттернами Mediator и State, создавая архитектуры, где компоненты полностью независимы, а взаимодействие происходит через централизованные события.

  • State + Observer: управление состоянием приложения и уведомление UI.
  • Mediator + Observer: центральный объект координирует события между различными компонентами.

Оптимизация и ограничения

  • Избегать глубоких вложенных структур без необходимости, чтобы минимизировать накладные расходы на отслеживание изменений.
  • Использовать batch при массовых обновлениях для снижения количества вызовов подписчиков.
  • Отписка обязательна для временных компонентов, чтобы избежать утечек памяти.

Заключение по структуре паттерна

Observer в Bliss.js реализован через лёгкий и интуитивный интерфейс: observe, subscribe, unsubscribe. Глубокое отслеживание изменений, фильтрация, поддержка batched updates и интеграция с UI делают его универсальным инструментом для построения реактивных приложений на чистом JavaScript.