Ett designmönster är en mall som löser ett vanligt återkommande problem inom mjukvarudesign.

Observatörsmönstret, även känt som publicera-prenumerera-mönstret, är ett beteendemönster. Det låter dig meddela flera objekt eller prenumeranter om alla händelser som publiceras i objektet de observerar.

Här får du lära dig hur du implementerar observatörsdesignmönstret i TypeScript.

Observatörsmönstret

Observatörsmönstret fungerar genom att definiera en en-till-många-relation mellan utgivaren och dess prenumeranter. När en händelse inträffar i utgivaren kommer den att meddela alla prenumeranter till den händelsen. Ett utbrett exempel på detta mönster är JavaScript-händelselyssnare.

För sammanhanget, anta att du bygger en lagerspårare som håller reda på antalet produkter i din butik. I det här fallet är din butik ämnet/utgivaren och ditt lager är observatören/prenumeranten. Att använda observatörsdesignmönstret skulle vara optimalt i denna situation.

I observatörsdesignmönstret måste din ämnesklass implementera tre metoder:

instagram viewer
  • En bifoga metod. Denna metod lägger till en observatör till ämnet.
  • A lösgöra metod. Denna metod tar bort en observatör från ett ämne.
  • A meddela/uppdatera metod. Denna metod meddelar försökspersonens observatörer när tillståndet ändras i ämnet.

Din observatörsklass måste implementera en metod, den uppdatering metod. Denna metod reagerar när det sker en förändring i ämnets tillstånd.

Implementering av ämnes- och observatörsklasserna

Det första steget för att implementera detta mönster är att skapa gränssnitt för ämnet och observatörsklassen, för att säkerställa att de implementerar de korrekta metoderna:

// Ämne/Publisher Interface
gränssnittÄmne{
attachObserver (observatör: observatör): tomhet;
detachObserver (observatör: observatör): tomhet;
notifyObserver(): tomhet;
}

// Observer/Subscriber Interface
gränssnittObservatör{
uppdatering(ämne: Ämne): tomhet;
}

Gränssnitten i kodblocket ovan definierar metoderna som dina betongklasser måste implementera.

En konkret ämnesklass

Nästa steg är att implementera en konkret ämnesklass som implementerar Ämne gränssnitt:

// Ämne
klassLagraredskapÄmne{}

Initiera sedan Ämnes tillstånd i Lagra klass. Ämnets observatörer kommer att reagera på förändringar i detta tillstånd.

I det här fallet är staten ett nummer, och observatörerna kommer att reagera på en ökning av antalet:

// Ämnesstatus
privat numberOfProducts: antal;

Initiera sedan en uppsättning observatörer. Den här arrayen är hur du kommer att hålla reda på observatörerna:

// initierar observatörer
privat observatörer: Observer[] = [];

Du kanske hittar några implementeringar av observatörsmönstret med hjälp av a Ställ in datastruktur i stället för en array för att hålla reda på observatören. Att använda en uppsättning säkerställer att samma observatör inte dyker upp två gånger. Om du istället vill använda en array bör du leta efter dubbla observatörer i din bifoga metod.

Därefter bör du implementera Ämnemetoder -bifoga, lösgöra, och meddela/uppdatera—i din betongklass.

För att genomföra bifoga metod, kontrollera först om observatören redan är ansluten och skicka ett fel om det är det. Annars lägger du till observatören till arrayen med hjälp av JavaScript array-metod, skjuta på:

// Bifoga observatör(er)
attachObserver (observatör: observatör): tomhet {
// Kontrollera om observatören redan är kopplad
konst observerExists = detta.observers.includes (observatör);

if (observatörExists) {
kastanyFel('Observer har redan prenumererats');
}

// Lägg till en ny observatör
detta.observatörer.skjuta på(observatör);
}

Nästa, implementera din lösgöra genom att hitta indexet och ta bort det från arrayen med hjälp av JavaScript splitsa metod.

Det kan finnas scenarier där observatören du försöker koppla bort redan har kopplats bort eller inte har prenumererat på från början. Du bör hantera dessa scenarier genom att lägga till ett villkorligt uttalande för att kontrollera om observatören finns i arrayen eller uppsättningen.

// Avskiljande observatör(er)
detachObserver (observatör: observatör): tomhet {
trösta.logga(`Avskiljande observatör ${JSON.stringify (observatör)}`);
konst observerIndex = detta.observers.indexOf (observatör);

if (observerIndex -1) {
kastanyFel('Observatören finns inte');
}

detta.observatörer.splitsa(observerIndex, 1);
console.log('Observatör frikopplad...');
}

Nästa, implementera din meddela/uppdatera metod genom att gå över din lista över observatörer och anropa uppdatering metod för var och en:

// Meddelar observatörer
notifyObserver(): tomhet {
console.log('Meddelar observatörer...');

för (konst observatör avdetta.observatörer) {
observer.update(detta);
}
}

Slutligen, för Ämne klass, implementera en metod som manipulerar tillståndet och sedan meddelar observatörerna om förändringen genom att anropa deras meddela/uppdatera metod. Det här exemplet är en förenkling av hur en person kan utföra en handling och sedan informera observatörer:

// Ändra status och meddela observatörer
nyprodukt (produkter: antal): tomhet {
detta.numberOfProducts += produkter;
console.log('Ny produkt har lagts till i butiken');
detta.notifyObserver();
}

Konkreta observatörsklasser

Skapa en eller flera observatörsklasser för att prenumerera på utgivaren. Varje observatörsklass måste implementera Observatör gränssnitt.

Observatörsklasserna kommer att implementera en meddela/uppdatera metod som endast ämnet de observerar ska anropa. Den här metoden bör innehålla all affärslogik du behöver köra som svar på en förändring i ämnets tillstånd:

// Betongobservatör 1
klassLagerredskapObservatör{
uppdatering(): tomhet {
console.log('Ny produkt läggs till i butiken, uppdaterar lager...');
// Verklig affärslogik går här...
}
}

// Concrete Observer 2
klassKundredskapObservatör{
uppdatering(): tomhet {
console.log('Ny produkt lagt till i butiken, jag måste gå och kolla in den...');
// Verklig affärslogik går här...
}
}

Använda observatörsmönstret

För att använda detta mönster, instansiera de konkreta ämnes- och observatörsklasserna. När du har gjort det ringer du ämnet bifoga metod och skicka Observer-instansen som ett argument. Som svar kommer försökspersonen att lägga till den instansen till sin lista över observatörer:

// Instanterande subjekt och observatör
konst butik = ny Lagra();
konst inventering = ny Lager();
konst kund = ny Kund()

// Prenumerera objekt till utgivare
Lagra.attachObserver(lager);
Lagra.attachObserver(kund);
// Ändring av ämnesstatus
Lagra.ny produkt(30);

Denna kod simulerar en tillståndsändring. Ändringen kommer att utlösa meddelandemetoden på Ämne klass. Denna metod kallar i sin tur för meddela metod på var och en av dess observatörer. Varje observatör kommer sedan att köra sin egen affärslogik.

Du bör bara använda det här mönstret när ändringarna av tillståndet för ett objekt påverkar andra objekt, och den inblandade uppsättningen objekt är okänd eller dynamisk.

Fördelar med att använda observatörsmönstret

Genom att använda det här mönstret i din kod kan du behålla öppna/stäng-principen. Du kan lägga till så många prenumeranter som du vill och upprätta relationer mellan objekt under körning, utan att ändra ämnets kod.