Шаблонът за проектиране е шаблон, който решава често повтарящ се проблем в софтуерния дизайн.

Моделът на наблюдател, известен също като модел публикуване-абониране, е поведенчески модел. Тя ви позволява да уведомите множество обекти или абонати за всяко събитие, което е публикувано в обекта, който те наблюдават.

Тук ще научите как да внедрите шаблона за проектиране на наблюдател в TypeScript.

Моделът на наблюдателя

Моделът на наблюдател работи, като дефинира връзка "един към много" между издателя и неговите абонати. Когато възникне събитие в издателя, той ще уведоми всички абонати за това събитие. Един широко разпространен пример за този модел е JavaScript слушатели на събития.

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

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

instagram viewer
  • Ан прикачвам метод. Този метод добавя наблюдател към обекта.
  • А отделям се метод. Този метод премахва наблюдател от обект.
  • А уведомявам/актуализирам метод. Този метод уведомява наблюдателите на обекта, когато състоянието се промени в обекта.

Вашият клас наблюдател трябва да имплементира един метод, the актуализация метод. Този метод реагира, когато има промяна в състоянието на обекта.

Внедряване на класовете Subject и Observer

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

// Интерфейс Тема/Издател
интерфейсПредмет{
attachObserver (наблюдател: Наблюдател): невалиден;
detachObserver (наблюдател: Наблюдател): невалиден;
notifyObserver(): невалиден;
}

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

Интерфейсите в кодовия блок по-горе дефинират методите, които вашите конкретни класове трябва да прилагат.

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

Следващата стъпка е да се внедри конкретен предметен клас, който прилага Предмет интерфейс:

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

След това инициализирайте Предметсъстояние в Магазин клас. Наблюдателите на обекта ще реагират на промените в това състояние.

В този случай състоянието е число и наблюдателите ще реагират на увеличаване на числото:

// Състояние на субекта
частен numberOfProducts: брой;

След това инициализирайте масив от наблюдатели. Този масив е начинът, по който ще следите наблюдателите:

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

Може да намерите някои реализации на модела на наблюдателя, използвайки a Задаване на структура от данни вместо масив, за да следите наблюдателя. Използването на набор ще гарантира, че един и същ наблюдател няма да се появи два пъти. Ако вместо това искате да използвате масив, трябва да проверите за дублиращи се наблюдатели във вашия прикачвам метод.

След това трябва да внедрите Предметметоди на -прикачвам, отделям се, и уведомявам/актуализирам— във вашия бетонен клас.

За прилагане на прикачвам метод, първо проверете дали наблюдателят вече е прикачен и изведете грешка, ако е. В противен случай добавете наблюдателя към масива, като използвате Метод на JavaScript масив, тласък:

// Прикачване на наблюдател(и)
attachObserver (наблюдател: Наблюдател): невалиден {
// Проверете дали наблюдателят вече е прикачен
конст наблюдателСъществува = това.observers.includes (наблюдател);

if (observerExists) {
хвърлямновГрешка(„Наблюдателят вече е абониран“);
}

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

След това внедрите своя отделям се чрез намиране на индекса и премахването му от масива с помощта на JavaScript снаждане метод.

Възможно е да има сценарии, при които наблюдателят, който се опитвате да отделите, вече е бил отделен или не е бил абониран на първо място. Трябва да се справите с тези сценарии, като добавите условен израз, за ​​да проверите дали наблюдателят е в масива или набора, според случая.

// Отделяне на наблюдател(и)
detachObserver (наблюдател: Наблюдател): невалиден {
конзола.log(„Отделящ се наблюдател ${JSON.stringify (наблюдател)}`);
конст наблюдателИндекс = това.observers.indexOf (наблюдател);

if (observerIndex -1) {
хвърлямновГрешка(„Наблюдателят не съществува“);
}

това.наблюдатели.снаждане(наблюдателИндекс, 1);
console.log('Отделен наблюдател...');
}

След това внедрите своя уведомявам/актуализирам метод, като преминете през списъка си с наблюдатели и извикате актуализация метод на всеки един:

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

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

И накрая, за Предмет клас, имплементирайте метод, който манипулира състоянието и след това уведомява наблюдателите за промяната, като извиква техния уведомявам/актуализирам метод. Този пример е опростяване на това как субект може да извърши действие и след това да информира наблюдателите:

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

Класове за конкретни наблюдатели

Създайте клас или класове наблюдател, за да се абонирате за издателя. Всеки клас наблюдател трябва да изпълнява Наблюдател интерфейс.

Класовете наблюдатели ще изпълняват a уведомявам/актуализирам метод, който трябва да извиква само обектът, който те наблюдават. Този метод трябва да съдържа цялата бизнес логика, която трябва да стартирате в отговор на промяна в състоянието на субекта:

// Конкретен наблюдател 1
класСкладова наличностинструментиНаблюдател{
актуализация(): невалиден {
console.log('Нов продукт, добавен към магазина, актуализиране на инвентара...');
// Действителната бизнес логика е тук...
}
}

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

Използване на модела на наблюдател

За да използвате този модел, създайте конкретни класове субект и наблюдател. След като го направите, обадете се на субекта прикачвам метод и предайте екземпляра на Observer като аргумент. В отговор субектът ще добави този екземпляр към своя списък с наблюдатели:

// Създаване на субект и наблюдател
конст магазин = нов Магазин();
конст инвентар = нов Складова наличност();
конст клиент = нов клиент()

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

Този код симулира промяна на състоянието. Промяната ще задейства метода за уведомяване на Предмет клас. Този метод от своя страна извиква уведомявам метод на всеки от своите наблюдатели. След това всеки наблюдател ще управлява своя собствена бизнес логика.

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

Предимства от използването на модела на наблюдател

Използването на този модел във вашия код ви позволява да поддържате принципа отваряне/затваряне. Можете да добавите толкова абонати, колкото желаете, и да установите връзки между обекти по време на изпълнение, без да променяте кода на субекта.