Ένα σχέδιο σχεδίασης είναι ένα πρότυπο που λύνει ένα συχνά επαναλαμβανόμενο πρόβλημα στο σχεδιασμό λογισμικού.
Το μοτίβο παρατηρητή, γνωστό και ως μοτίβο δημοσίευσης-εγγραφής, είναι ένα μοτίβο συμπεριφοράς. Σας επιτρέπει να ειδοποιείτε πολλά αντικείμενα ή συνδρομητές για οποιοδήποτε συμβάν που δημοσιεύεται στο αντικείμενο που παρατηρούν.
Εδώ θα μάθετε πώς να εφαρμόσετε το μοτίβο σχεδίασης παρατηρητή στο TypeScript.
Το μοτίβο του παρατηρητή
Το μοτίβο παρατηρητή λειτουργεί ορίζοντας μια σχέση ένα προς πολλά μεταξύ του εκδότη και των συνδρομητών του. Όταν συμβεί ένα συμβάν στον εκδότη, θα ειδοποιήσει όλους τους συνδρομητές σε αυτό το συμβάν. Ένα ευρέως διαδεδομένο παράδειγμα αυτού του μοτίβου είναι Ακρόαση συμβάντων JavaScript.
Για το πλαίσιο, ας υποθέσουμε ότι δημιουργείτε έναν ανιχνευτή αποθέματος που παρακολουθεί τον αριθμό των προϊόντων στο κατάστημά σας. Σε αυτήν την περίπτωση, το κατάστημά σας είναι το υποκείμενο/εκδότης και το απόθεμά σας είναι ο παρατηρητής/συνδρομητής. Η χρήση του σχεδίου του παρατηρητή θα ήταν βέλτιστη σε αυτήν την περίπτωση.
Στο μοτίβο σχεδίασης παρατηρητή, η θεματική σας τάξη πρέπει να εφαρμόσει τρεις μεθόδους:
- Ενα συνδέω μέθοδος. Αυτή η μέθοδος προσθέτει έναν παρατηρητή στο θέμα.
- ΕΝΑ αποσπώ μέθοδος. Αυτή η μέθοδος αφαιρεί έναν παρατηρητή από ένα θέμα.
- ΕΝΑ ειδοποίηση/ενημέρωση μέθοδος. Αυτή η μέθοδος ειδοποιεί τους παρατηρητές του υποκειμένου όταν αλλάζει η κατάσταση στο θέμα.
Η κλάση παρατηρητή σας πρέπει να εφαρμόσει μία μέθοδο, την εκσυγχρονίζω μέθοδος. Αυτή η μέθοδος αντιδρά όταν υπάρχει αλλαγή στην κατάσταση του θέματός της.
Υλοποίηση των τάξεων Subject και Observer
Το πρώτο βήμα για την εφαρμογή αυτού του μοτίβου είναι η δημιουργία διεπαφών για το θέμα και την τάξη παρατηρητή, για να διασφαλιστεί ότι εφαρμόζουν τις σωστές μεθόδους:
// Διεπαφή θέματος/εκδότη
διεπαφήΘέμα{
attachObserver (παρατηρητής: Παρατηρητής): κενός;
detachObserver (παρατηρητής: Παρατηρητής): κενός;
notifyObserver(): κενός;
}
// Διασύνδεση παρατηρητή/συνδρομητή
διεπαφήΠαρατηρητής{
εκσυγχρονίζω(θέμα: Θέμα): κενός;
}
Οι διεπαφές στο μπλοκ κώδικα παραπάνω καθορίζουν τις μεθόδους που πρέπει να εφαρμόσουν οι συγκεκριμένες κλάσεις σας.
Μια συγκεκριμένη κατηγορία θεμάτων
Το επόμενο βήμα είναι η υλοποίηση μιας συγκεκριμένης τάξης θεμάτων που υλοποιεί το Θέμα διεπαφή:
// Θέμα
τάξηΚατάστημαυλοποιείΘέμα{}
Στη συνέχεια, αρχικοποιήστε το Θέμακατάσταση του Κατάστημα τάξη. Οι παρατηρητές του υποκειμένου θα αντιδράσουν σε αλλαγές σε αυτήν την κατάσταση.
Σε αυτή την περίπτωση, το κράτος είναι ένας αριθμός και οι παρατηρητές θα αντιδράσουν σε μια αύξηση του αριθμού:
// Κατάσταση θέματος
ιδιωτικός numberOfProducts: αριθμός;
Στη συνέχεια, αρχικοποιήστε μια σειρά από παρατηρητές. Αυτός ο πίνακας είναι ο τρόπος με τον οποίο θα παρακολουθείτε τους παρατηρητές:
// αρχικοποίηση παρατηρητών
ιδιωτικός παρατηρητές: Παρατηρητής[] = [];
Μπορεί να βρείτε κάποιες υλοποιήσεις του σχεδίου παρατηρητή χρησιμοποιώντας μια δομή δεδομένων συνόλου στη θέση ενός πίνακα για να παρακολουθείτε τον παρατηρητή. Η χρήση ενός συνόλου θα διασφαλίσει ότι ο ίδιος παρατηρητής δεν θα εμφανιστεί δύο φορές. Αν θέλετε να χρησιμοποιήσετε έναν πίνακα, θα πρέπει να ελέγξετε για διπλότυπους παρατηρητές στο δικό σας συνδέω μέθοδος.
Στη συνέχεια, θα πρέπει να εφαρμόσετε το Θέμαμέθοδοι -συνδέω, αποσπώ, και ειδοποίηση/ενημέρωση—στη συγκεκριμένη τάξη σας.
Για την εφαρμογή του συνδέω μέθοδο, πρώτα ελέγξτε αν ο παρατηρητής είναι ήδη συνδεδεμένος και ρίξτε ένα σφάλμα εάν είναι. Διαφορετικά, προσθέστε τον παρατηρητή στον πίνακα χρησιμοποιώντας το Μέθοδος πίνακα JavaScript, Σπρώξτε:
// Επισύναψη παρατηρητή (ών)
attachObserver (παρατηρητής: Παρατηρητής): κενός {
// Ελέγξτε εάν ο παρατηρητής έχει ήδη προσαρτηθεί
συνθ παρατηρητήςΥπάρχει = Αυτό.παρατηρητές.περιλαμβάνει (παρατηρητής);if (observerExists) {
βολήνέοςΛάθος('Ο παρατηρητής έχει ήδη εγγραφεί');
}
// Προσθήκη νέου παρατηρητή
Αυτό.παρατηρητές.Σπρώξτε(παρατηρητής);
}
Στη συνέχεια, εφαρμόστε το δικό σας αποσπώ μέθοδος βρίσκοντας το ευρετήριο και αφαιρώντας το από τον πίνακα χρησιμοποιώντας τη JavaScript συνδέω μέθοδος.
Μπορεί να υπάρχουν σενάρια όπου ο παρατηρητής που προσπαθείτε να αποσπάσετε έχει ήδη αποσπαστεί ή δεν ήταν εγγεγραμμένος εξαρχής. Θα πρέπει να χειριστείτε αυτά τα σενάρια προσθέτοντας μια δήλωση υπό όρους για να ελέγξετε εάν ο παρατηρητής βρίσκεται στον πίνακα ή στο σύνολο ανάλογα με την περίπτωση.
// Αποσύνδεση παρατηρητή (ων)
detachObserver (παρατηρητής: Παρατηρητής): κενός {
κονσόλα.κούτσουρο(`Αποσπώμενος παρατηρητής ${JSON.stringify (παρατηρητής)}`);
συνθ παρατηρητήςΔείκτης = Αυτό.observers.indexOf (παρατηρητής);if (observerIndex -1) {
βολήνέοςΛάθος('Ο παρατηρητής δεν υπάρχει');
}
Αυτό.παρατηρητές.συνδέω(παρατηρητήςΕυρετήριο, 1);
console.log('Ο παρατηρητής αποσπάστηκε...');
}
Στη συνέχεια, εφαρμόστε το δικό σας ειδοποίηση/ενημέρωση τη μέθοδο κάνοντας looping πάνω από τη λίστα των παρατηρητών σας και καλώντας το εκσυγχρονίζω μέθοδος του καθενός:
// Ειδοποίηση παρατηρητών
notifyObserver(): κενός {
console.log('Ειδοποίηση παρατηρητών...');
Για (συνθ παρατηρητής τουΑυτό.παρατηρητές) {
Observer.update(Αυτό);
}
}
Τέλος, για την Θέμα class, εφαρμόστε μια μέθοδο που χειρίζεται την κατάσταση και στη συνέχεια ειδοποιεί τους παρατηρητές για την αλλαγή καλώντας τους ειδοποίηση/ενημέρωση μέθοδος. Αυτό το παράδειγμα είναι μια απλοποίηση του τρόπου με τον οποίο ένα υποκείμενο μπορεί να εκτελέσει μια ενέργεια και στη συνέχεια να ενημερώσει τους παρατηρητές:
// Αλλαγή κατάστασης και ειδοποίηση παρατηρητών
νέοΠροϊόν (προϊόντα: αριθμός): κενός {
Αυτό.numberOfProducts += προϊόντα;
console.log('Νέο προϊόν προστέθηκε στο κατάστημα');
Αυτό.notifyObserver();
}
Τμήματα Concrete Observer
Δημιουργήστε μια τάξη ή τάξεις παρατηρητή, για να εγγραφείτε στον εκδότη. Κάθε κλάση παρατηρητή πρέπει να εφαρμόσει το Παρατηρητής διεπαφή.
Οι τάξεις παρατηρητών θα εφαρμόσουν α ειδοποίηση/ενημέρωση μέθοδο την οποία πρέπει να καλεί μόνο το θέμα που παρατηρούν. Αυτή η μέθοδος θα πρέπει να περιέχει όλη την επιχειρηματική λογική που πρέπει να εκτελέσετε ως απάντηση σε μια αλλαγή στην κατάσταση του θέματος:
// Concrete Observer 1
τάξηΚαταγραφή εμπορευμάτωνυλοποιείΠαρατηρητής{
εκσυγχρονίζω(): κενός {
console.log('Προστέθηκε νέο προϊόν στο κατάστημα, ενημέρωση αποθέματος...');
// Η πραγματική επιχειρηματική λογική πηγαίνει εδώ...
}
}
// Concrete Observer 2
τάξηΠελάτηςυλοποιείΠαρατηρητής{
εκσυγχρονίζω(): κενός {
console.log('Προστέθηκε νέο προϊόν στο κατάστημα, πρέπει να πάω να το ελέγξω...');
// Η πραγματική επιχειρηματική λογική πηγαίνει εδώ...
}
}
Χρησιμοποιώντας το μοτίβο παρατηρητή
Για να χρησιμοποιήσετε αυτό το μοτίβο, δημιουργήστε τις συγκεκριμένες τάξεις θέματος και παρατηρητή. Μόλις το κάνετε, καλέστε το Θέμα συνδέω μέθοδο και περάστε το παράδειγμα Observer ως όρισμα. Σε απάντηση, το υποκείμενο θα προσθέσει αυτό το παράδειγμα στη λίστα των παρατηρητών του:
// Instantiating Subject και Observer
συνθ κατάστημα = νέος Κατάστημα();
συνθ απόθεμα = νέος Καταγραφή εμπορευμάτων();
συνθ πελάτης = νέος Πελάτης()
// Εγγραφή αντικειμένων στον εκδότη
κατάστημα.attachObserver(καταγραφή εμπορευμάτων);
κατάστημα.attachObserver(πελάτης);
// Αλλαγή κατάστασης θέματος
κατάστημα.καινουργιο ΠΡΟΪΟΝ(30);
Αυτός ο κώδικας προσομοιώνει μια αλλαγή κατάστασης. Η αλλαγή θα ενεργοποιήσει τη μέθοδο ειδοποίησης στο Θέμα τάξη. Αυτή η μέθοδος, με τη σειρά της, καλεί το κοινοποιώ μέθοδο σε κάθε παρατηρητή της. Στη συνέχεια, κάθε παρατηρητής θα τρέξει τη δική του επιχειρηματική λογική.
Θα πρέπει να χρησιμοποιείτε αυτό το μοτίβο μόνο όταν οι αλλαγές στην κατάσταση ενός αντικειμένου επηρεάζουν άλλα αντικείμενα και το σύνολο των εμπλεκόμενων αντικειμένων είναι άγνωστο ή δυναμικό.
Πλεονεκτήματα της χρήσης του μοτίβου παρατηρητή
Η χρήση αυτού του μοτίβου στον κώδικά σας σάς επιτρέπει να διατηρήσετε την αρχή ανοίγματος/κλεισίματος. Μπορείτε να προσθέσετε όσους συνδρομητές θέλετε και να δημιουργήσετε σχέσεις μεταξύ των αντικειμένων κατά το χρόνο εκτέλεσης, χωρίς να αλλάξετε τον κώδικα του θέματος.