Шаблон проектирования — это шаблон, который решает часто повторяющуюся проблему при проектировании программного обеспечения.

Паттерн наблюдателя, также известный как паттерн публикации-подписки, представляет собой поведенческий паттерн. Это позволяет вам уведомлять несколько объектов или подписчиков о любом событии, которое публикуется в объекте, за которым они наблюдают.

Здесь вы узнаете, как реализовать шаблон проектирования наблюдателя в TypeScript.

Шаблон наблюдателя

Шаблон наблюдателя работает, определяя отношение «один ко многим» между издателем и его подписчиками. Когда в издателе происходит событие, он уведомляет всех подписчиков об этом событии. Одним из широко распространенных примеров этого шаблона является Слушатели событий JavaScript.

Для контекста предположим, что вы создаете средство отслеживания запасов, которое отслеживает количество товаров в вашем магазине. В этом случае ваш магазин является субъектом/издателем, а ваш инвентарь – наблюдателем/подписчиком. Использование шаблона проектирования наблюдателя было бы оптимальным в этой ситуации.

instagram viewer

В шаблоне проектирования наблюдателя ваш подчиненный класс должен реализовать три метода:

  • Ан прикреплять метод. Этот метод добавляет к субъекту наблюдателя.
  • А отделить метод. Этот метод удаляет наблюдателя от субъекта.
  • А уведомить/обновить метод. Этот метод уведомляет наблюдателей субъекта об изменении состояния субъекта.

Ваш класс наблюдателя должен реализовать один метод, обновлять метод. Этот метод реагирует на изменение состояния субъекта.

Реализация классов Subject и Observer

Первым шагом к реализации этого шаблона является создание интерфейсов для класса объекта и наблюдателя, чтобы убедиться, что они реализуют правильные методы:

// Интерфейс субъекта/издателя
интерфейсПредмет{
attachObserver (наблюдатель: Наблюдатель): пустота;
detachObserver (наблюдатель: Наблюдатель): пустота;
уведомитьнаблюдателя(): пустота;
}

// Интерфейс наблюдателя/подписчика
интерфейсНаблюдатель{
обновлять(тема: Тема): пустота;
}

Интерфейсы в приведенном выше блоке кода определяют методы, которые должны быть реализованы вашими конкретными классами.

Конкретный предметный класс

Следующим шагом является реализация конкретного предметного класса, реализующего Предмет интерфейс:

// Предмет
сортМагазинреализуетПредмет{}

Далее инициализируйте Предметсостояние в Магазин сорт. Наблюдатели субъекта будут реагировать на изменения этого состояния.

В этом случае состояние — это число, и наблюдатели будут реагировать на увеличение числа:

// Состояние субъекта
частный количество продуктов: количество;

Затем инициализируйте массив наблюдателей. В этом массиве вы будете отслеживать наблюдателей:

// инициализация наблюдателей
частный наблюдатели: Наблюдатель[] = [];

Вы можете найти некоторые реализации шаблона наблюдателя, используя Установить структуру данных вместо массива для отслеживания наблюдателя. Использование набора гарантирует, что один и тот же наблюдатель не появится дважды. Если вы хотите вместо этого использовать массив, вам следует проверить наличие повторяющихся наблюдателей в вашем прикреплять метод.

Далее следует реализовать Предметметоды —прикреплять, отделить, и уведомить/обновить— в вашем конкретном классе.

Для реализации прикреплять метода, сначала проверьте, не подключен ли уже наблюдатель, и выдайте ошибку, если это так. В противном случае добавьте наблюдателя в массив с помощью Метод массива JavaScript, толкать:

// Присоединение наблюдателя(ей)
attachObserver (наблюдатель: Наблюдатель): пустота {
// Проверяем, не был ли уже прикреплен наблюдатель
константа наблюдатель существует = этот.observers.includes (наблюдатель);

если (наблюдатель существует) {
бросатьновыйОшибка('Обозреватель уже подписан');
}

// Добавляем нового наблюдателя
этот.наблюдатели.толкать(наблюдатель);
}

Далее реализуйте свой отделить метод, найдя индекс и удалив его из массива с помощью JavaScript соединение метод.

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

// Отсоединение наблюдателя(ей)
detachObserver (наблюдатель: Наблюдатель): пустота {
консоль.бревно(`Отсоединение наблюдателя ${JSON.stringify (наблюдатель)}`);
константа индекс наблюдателя = этот.observers.indexOf (наблюдатель);

если (индекс_наблюдателя -1) {
бросатьновыйОшибка("Наблюдатель не существует");
}

этот.наблюдатели.сращивание(индекс наблюдателя, 1);
console.log('Наблюдатель отключен...');
}

Далее реализуйте свой уведомить/обновить метод, перебирая список наблюдателей и вызывая метод обновлять метод каждого из них:

// Уведомление наблюдателей
уведомитьнаблюдателя(): пустота {
console.log('Уведомление наблюдателей...');

для (константа наблюдатель изэтотнаблюдатели) {
наблюдатель.обновление(этот);
}
}

Наконец, для Предмет класс, реализуйте метод, который манипулирует состоянием, а затем уведомляет наблюдателей об изменении, вызывая их уведомить/обновить метод. Этот пример является упрощением того, как субъект может выполнить действие, а затем сообщить наблюдателям:

// Изменение состояния и уведомление наблюдателей
новыйПродукт (продукты: количество): пустота {
этот.numberOfProducts += продукты;
console.log('В магазин добавлен новый товар');
этот.notifyObserver();
}

Конкретные классы наблюдателей

Создайте класс или классы наблюдателя, чтобы подписаться на издателя. Каждый класс наблюдателя должен реализовать Наблюдатель интерфейс.

Классы-наблюдатели будут реализовывать уведомить/обновить метод, который должен вызывать только субъект, за которым они наблюдают. Этот метод должен содержать всю бизнес-логику, которую вам нужно запустить в ответ на изменение состояния субъекта:

// Бетонный наблюдатель 1
сортИнвентарьреализуетНаблюдатель{
обновлять(): пустота {
console.log('В магазин добавлен новый товар, обновление ассортимента...');
// Здесь находится реальная бизнес-логика...
}
}

// Бетонный наблюдатель 2
сортКлиентреализуетНаблюдатель{
обновлять(): пустота {
console.log('Новый товар добавлен в магазин, надо посмотреть...');
// Здесь находится реальная бизнес-логика...
}
}

Использование шаблона наблюдателя

Чтобы использовать этот шаблон, создайте экземпляры конкретных классов субъекта и наблюдателя. Сделав это, позвоните прикреплять и передайте экземпляр Observer в качестве аргумента. В ответ субъект добавит этот экземпляр в свой список наблюдателей:

// Создание субъекта и наблюдателя
константа магазин = новый Магазин();
константа инвентарь = новый Инвентарь();
константа клиент = новый Клиент()

// Подписка объектов на публикатор
магазин.attachObserver(инвентарь);
магазин.attachObserver(клиент);
// Изменение состояния субъекта
магазин.новый продукт(30);

Этот код имитирует изменение состояния. Изменение вызовет метод уведомления на Предмет сорт. Этот метод, в свою очередь, вызывает поставить в известность метод на каждом из своих наблюдателей. Затем каждый наблюдатель будет выполнять свою собственную бизнес-логику.

Этот шаблон следует использовать только тогда, когда изменения состояния одного объекта влияют на другие объекты, а набор вовлеченных объектов неизвестен или динамичен.

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

Использование этого шаблона в вашем коде позволяет вам поддерживать принцип открытия/закрытия. Вы можете добавлять столько подписчиков, сколько хотите, и устанавливать отношения между объектами во время выполнения, не изменяя код субъекта.