Collection proxies и decorators

Backbone.js предоставляет мощные инструменты для управления коллекциями моделей через объект Backbone.Collection. В продвинутых сценариях работы с коллекциями применяются Collection proxies и decorators, позволяющие гибко расширять функциональность коллекций без изменения их исходного поведения.


Collection proxies

Collection proxy — это объект, который оборачивает оригинальную коллекцию и переопределяет часть её методов или добавляет новые, сохраняя при этом доступ к исходной коллекции. Такой подход позволяет:

  • Создавать виртуальные представления коллекций (например, фильтры или сортировки на лету).
  • Поддерживать независимые состояния коллекции без дублирования данных.
  • Инкапсулировать сложную логику работы с набором моделей.

Создание прокси-коллекции

const originalCollection = new Backbone.Collection([
  { id: 1, name: 'Alice', active: true },
  { id: 2, name: 'Bob', active: false },
  { id: 3, name: 'Carol', active: true }
]);

const proxyCollection = new Backbone.Collection();

// Синхронизация данных с оригиналом
originalCollection.on('add remove change', function() {
  proxyCollection.reset(originalCollection.models);
});

// Добавление кастомного метода фильтрации
proxyCollection.activeModels = function() {
  return this.filter(model => model.get('active'));
};

В этом примере proxyCollection отражает текущее состояние originalCollection, но при этом содержит дополнительные методы, например activeModels, которые позволяют работать только с активными элементами.

Преимущества использования прокси

  1. Изоляция логики: можно создать несколько прокси с разными правилами фильтрации или сортировки.
  2. Минимизация изменений исходного кода: нет необходимости модифицировать базовую коллекцию.
  3. Поддержка событий Backbone: прокси-коллекция может реагировать на изменения исходной коллекции и уведомлять своих слушателей.

Decorators для коллекций

Decorator — это паттерн, позволяющий динамически расширять функциональность объекта. Для коллекций Backbone.js это означает добавление новых методов или переопределение существующих без изменения базового класса.

Пример создания декоратора

function timestampDecorator(collection) {
  collection.getTimestamps = function() {
    return this.map(model => model.get('createdAt'));
  };

  collection.addWithTimestamp = function(attrs) {
    attrs.createdAt = new Date();
    this.add(attrs);
  };

  return collection;
}

let decoratedCollection = timestampDecorator(new Backbone.Collection());
decoratedCollection.addWithTimestamp({ id: 1, name: 'Dave' });
console.log(decoratedCollection.getTimestamps());

Декоратор позволяет:

  • Добавлять новые методы (getTimestamps, addWithTimestamp) к существующей коллекции.
  • Не нарушать оригинальную структуру класса.
  • Сохранять возможность дальнейшего расширения другими декораторами.

Составные декораторы

Можно комбинировать несколько декораторов, создавая цепочки расширений:

function loggingDecorator(collection) {
  const originalAdd = collection.add;
  collection.add = function(models, options) {
    console.log('Добавление моделей:', models);
    return originalAdd.call(this, models, options);
  };
  return collection;
}

let enhancedCollection = loggingDecorator(timestampDecorator(new Backbone.Collection()));
enhancedCollection.addWithTimestamp({ id: 2, name: 'Eve' });

В этом примере коллекция одновременно получает функционал декоратора для временных меток и ведение логов операций.


Отличие прокси от декораторов

Характеристика Collection Proxy Decorator
Цель Обертка с возможностью изменения поведения коллекции Расширение функциональности существующего объекта
Хранение данных Может дублировать или фильтровать модели оригинала Использует оригинальную коллекцию напрямую
Модификация оригинала Нет, изменения происходят через прокси Нет, декоратор расширяет объект, но не меняет базовый класс
Сценарии использования Фильтры, сортировки, виртуальные представления Добавление утилитных методов, логирование, вспомогательные операции

Практические советы

  1. Прокси лучше использовать для создания альтернативных представлений данных.
  2. Декораторы эффективны для утилитарных методов, не связанных с внутренней структурой коллекции.
  3. Оба подхода сохраняют совместимость с Backbone-событиями, что позволяет строить реактивные интерфейсы.
  4. Комбинирование прокси и декораторов позволяет создавать мощные расширяемые архитектуры без дублирования кода.

Использование с фильтрацией и сортировкой

const filteredProxy = new Backbone.Collection();
originalCollection.on('update', function() {
  const activeModels = originalCollection.where({ active: true });
  filteredProxy.reset(activeModels);
});

filteredProxy.comparator = 'name'; // автоматическая сортировка по имени
filteredProxy.sort();

Такой подход позволяет:

  • Поддерживать отдельные представления одной и той же коллекции.
  • Реагировать на изменения данных автоматически.
  • Легко комбинировать с декораторами для расширенной логики.

Collection proxies и decorators в Backbone.js дают возможность создавать гибкие и масштабируемые приложения, где коллекции можно адаптировать под различные требования интерфейса и бизнес-логики без изменения их исходного поведения.