Un modello di progettazione è un modello che risolve un problema comunemente ricorrente nella progettazione del software.
Il modello osservatore, noto anche come modello pubblicazione-sottoscrizione, è un modello comportamentale. Ti consente di notificare a più oggetti o abbonati qualsiasi evento pubblicato nell'oggetto che stanno osservando.
Qui imparerai come implementare il modello di progettazione dell'osservatore in TypeScript.
Il modello dell'osservatore
Il pattern osservatore funziona definendo una relazione uno-a-molti tra l'editore e i suoi abbonati. Quando si verifica un evento nell'editore, notificherà a tutti gli abbonati a quell'evento. Un esempio diffuso di questo modello è Listener di eventi JavaScript.
Per il contesto, supponi di creare un tracker dell'inventario che tenga traccia del numero di prodotti nel tuo negozio. In questo caso, il tuo negozio è il soggetto/editore e il tuo inventario è l'osservatore/abbonato. L'uso del modello di progettazione dell'osservatore sarebbe ottimale in questa situazione.
Nel modello di progettazione dell'osservatore, la tua classe soggetto deve implementare tre metodi:
- UN allegare metodo. Questo metodo aggiunge un osservatore al soggetto.
- UN staccare metodo. Questo metodo rimuove un osservatore da un soggetto.
- UN avvisare/aggiornare metodo. Questo metodo avvisa gli osservatori del soggetto quando lo stato cambia nel soggetto.
La tua classe di osservatore deve implementare un metodo, il aggiornamento metodo. Questo metodo reagisce quando c'è un cambiamento nello stato del soggetto.
Implementazione delle classi Soggetto e Osservatore
Il primo passo per implementare questo modello è creare interfacce per la classe soggetto e osservatore, per assicurarsi che implementino i metodi corretti:
// Interfaccia soggetto/editore
interfacciaSoggetto{
attachObserver (osservatore: Osservatore): vuoto;
detachObserver (osservatore: Osservatore): vuoto;
notificaOsservatore(): vuoto;
}
// Interfaccia osservatore/abbonato
interfacciaOsservatore{
aggiornamento(oggetto: Oggetto): vuoto;
}
Le interfacce nel blocco di codice sopra definiscono i metodi che le tue classi concrete devono implementare.
Una classe tematica concreta
Il passaggio successivo consiste nell'implementare una classe oggetto concreta che implementi il file Soggetto interfaccia:
// Soggetto
classeNegozioimplementaSoggetto{}
Successivamente, inizializza il file Soggettolo stato di Negozio classe. Gli osservatori del soggetto reagiranno ai cambiamenti di questo stato.
In questo caso, lo stato è un numero e gli osservatori reagiranno a un aumento del numero:
// Stato del soggetto
privato numeroDiProdotti: numero;
Successivamente, inizializza un array di osservatori. Questo array è il modo in cui tieni traccia degli osservatori:
// inizializzazione degli osservatori
privato osservatori: Osservatore[] = [];
Potresti trovare alcune implementazioni del pattern dell'osservatore usando a Imposta la struttura dei dati al posto di un array per tenere traccia dell'osservatore. L'uso di un set assicurerà che lo stesso osservatore non appaia due volte. Se invece vuoi utilizzare un array, dovresti verificare la presenza di osservatori duplicati nel tuo allegare metodo.
Successivamente, dovresti implementare il file Soggettometodi di—allegare, staccare, E avvisare/aggiornare- nella tua classe concreta.
Per implementare il allegare metodo, controlla prima se l'osservatore è già collegato e genera un errore se lo è. Altrimenti, aggiungi l'osservatore all'array usando il Metodo dell'array JavaScript, spingere:
// Attaccare osservatore(i)
attachObserver (osservatore: Osservatore): vuoto {
// Controlla se l'osservatore è già stato collegato
cost osservatoreEsiste = Questo.osservatori.include (osservatore);if (osservatoreEsiste) {
gettarenuovoErrore('L'osservatore è già stato abbonato');
}
// Aggiungi un nuovo osservatore
Questo.osservatori.spingere(osservatore);
}
Successivamente, implementa il tuo staccare trovando l'indice e rimuovendolo dall'array utilizzando JavaScript giunzione metodo.
Possono verificarsi scenari in cui l'osservatore che stai tentando di scollegare è già stato scollegato o non è stato iscritto in primo luogo. Dovresti gestire questi scenari aggiungendo un'istruzione condizionale per verificare se l'osservatore si trova nell'array o nel set, a seconda dei casi.
// Osservatore distaccante (s)
detachObserver (osservatore: Osservatore): vuoto {
consolare.tronco d'albero(`Osservatore distaccato ${JSON.stringify (osservatore)}`);
cost indiceosservatore = Questo.observers.indexOf (osservatore);if (observerIndex -1) {
gettarenuovoErrore("L'osservatore non esiste");
}
Questo.osservatori.giunzione(ObserverIndex, 1);
console.log('Osservatore distaccato...');
}
Successivamente, implementa il tuo avvisare/aggiornare metodo eseguendo il ciclo sull'elenco di osservatori e chiamando il metodo aggiornamento metodo di ognuno:
// Notifica agli osservatori
notificaOsservatore(): vuoto {
console.log('Avviso agli osservatori...');
per (cost osservatore DiQuesto.osservatori) {
osservatore.aggiornamento(Questo);
}
}
Infine, per il Soggetto class, implementa un metodo che manipola lo stato e quindi notifica agli osservatori la modifica chiamando il loro avvisare/aggiornare metodo. Questo esempio è una semplificazione di come un soggetto potrebbe eseguire un'azione e quindi informare gli osservatori:
// Cambio di stato e notifica agli osservatori
nuovoProdotto (prodotti: numero): vuoto {
Questo.numberOfProducts += prodotti;
console.log('Nuovo prodotto aggiunto al negozio');
Questo.notifyObserver();
}
Classi di osservatori concreti
Crea una o più classi di osservatori, per iscriverti all'editore. Ogni classe di osservatori deve implementare il Osservatore interfaccia.
Le classi di osservatori implementeranno a avvisare/aggiornare metodo che solo il soggetto che stanno osservando dovrebbe chiamare. Questo metodo dovrebbe contenere tutta la logica aziendale necessaria per eseguire in risposta a un cambiamento nello stato del soggetto:
// Osservatore concreto 1
classeInventarioimplementaOsservatore{
aggiornamento(): vuoto {
console.log('Nuovo prodotto aggiunto al negozio, aggiornamento dell'inventario...');
// La vera logica aziendale va qui...
}
}
// Osservatore concreto 2
classeClienteimplementaOsservatore{
aggiornamento(): vuoto {
console.log('Nuovo prodotto aggiunto allo store, devo andare a dare un'occhiata...');
// La vera logica aziendale va qui...
}
}
Usando il modello dell'osservatore
Per utilizzare questo modello, crea un'istanza delle classi concrete del soggetto e dell'osservatore. Dopo averlo fatto, chiama il Soggetto allegare metodo e passare l'istanza di Observer come argomento. In risposta, il soggetto aggiungerà quell'istanza al suo elenco di osservatori:
// Istanza di soggetto e osservatore
cost negozio = nuovo Negozio();
cost inventario = nuovo Inventario();
cost cliente = nuovo Cliente()
// Sottoscrizione di oggetti all'editore
negozio.attachObserver(inventario);
negozio.attachObserver(cliente);
// Modifica dello stato del soggetto
negozio.nuovo prodotto(30);
Questo codice simula un cambiamento di stato. La modifica attiverà il metodo di notifica sul file Soggetto classe. Questo metodo, a sua volta, chiama il metodo notificare metodo su ciascuno dei suoi osservatori. Ogni osservatore eseguirà quindi la propria logica di business.
Dovresti utilizzare questo modello solo quando le modifiche allo stato di un oggetto influiscono su altri oggetti e l'insieme di oggetti coinvolti è sconosciuto o dinamico.
Vantaggi dell'uso del modello dell'osservatore
L'utilizzo di questo modello nel codice consente di mantenere il principio di apertura/chiusura. Puoi aggiungere tutti i sottoscrittori che desideri e stabilire relazioni tra oggetti in fase di esecuzione, senza modificare il codice dell'oggetto.