Προγραμματισμός

Παρατηρητής και παρατηρήσιμος

Εδώ είναι το πρόβλημα: Σχεδιάζετε ένα πρόγραμμα που θα αποδίδει δεδομένα που περιγράφουν μια τρισδιάστατη σκηνή σε δύο διαστάσεις. Το πρόγραμμα πρέπει να είναι αρθρωτό και να επιτρέπει πολλαπλές, ταυτόχρονες προβολές της ίδιας σκηνής. Κάθε προβολή πρέπει να είναι σε θέση να εμφανίζει τη σκηνή από διαφορετικό πλεονεκτικό σημείο, υπό διαφορετικές συνθήκες φωτισμού. Το πιο σημαντικό, εάν αλλάξει κάποιο τμήμα της υποκείμενης σκηνής, οι προβολές πρέπει να ενημερωθούν.

Καμία από αυτές τις απαιτήσεις δεν αποτελεί ανυπέρβλητη πρόκληση προγραμματισμού. Εάν ο κωδικός που χειρίζεται κάθε απαίτηση έπρεπε να γραφτεί de novo, ωστόσο, θα προσθέσει σημαντική δουλειά στη συνολική προσπάθεια. Ευτυχώς, η υποστήριξη για αυτές τις εργασίες παρέχεται ήδη από τη βιβλιοθήκη κλάσης Java με τη μορφή διεπαφής Παρατηρητής και τάξη Αισθητός- και οι δύο εμπνέονται, εν μέρει, από τις απαιτήσεις της αρχιτεκτονικής MVC.

Η αρχιτεκτονική Model / View / Controller (MVC)

Η αρχιτεκτονική Model / View / Controller παρουσιάστηκε ως μέρος του Smalltalk, μιας δημοφιλούς αντικειμενοστρεφούς γλώσσας προγραμματισμού που εφευρέθηκε από τον Alan Kay. Το MVC σχεδιάστηκε για να μειώσει την προσπάθεια προγραμματισμού που απαιτείται για την κατασκευή συστημάτων που χρησιμοποιούν πολλαπλές, συγχρονισμένες παρουσιάσεις των ίδιων δεδομένων. Τα κεντρικά χαρακτηριστικά του είναι ότι το μοντέλο, οι ελεγκτές και οι προβολές αντιμετωπίζονται ως ξεχωριστές οντότητες και ότι οι αλλαγές που γίνονται στο μοντέλο πρέπει να αντικατοπτρίζονται αυτόματα σε κάθε μία από τις προβολές.

Εκτός από το παράδειγμα του προγράμματος που περιγράφεται στην παραπάνω παράγραφο, η αρχιτεκτονική Μοντέλου / Προβολή / Ελεγκτή μπορεί να χρησιμοποιηθεί για έργα όπως τα ακόλουθα:

  • Ένα πακέτο γραφημάτων που περιέχει ταυτόχρονες προβολές ραβδόγραμμα, γράφημα γραμμής και γράφημα πίτας των ίδιων δεδομένων.
  • Ένα σύστημα CAD, στο οποίο τμήματα του σχεδιασμού μπορούν να προβληθούν σε διαφορετικές μεγεθύνσεις, σε διαφορετικά παράθυρα και σε διαφορετικές κλίμακες.

Το σχήμα 1 απεικονίζει την αρχιτεκτονική MVC στη γενικότερη μορφή της. Υπάρχει ένα μοντέλο. Πολλοί ελεγκτές χειρίζονται το μοντέλο. πολλαπλές προβολές εμφανίζουν τα δεδομένα στο μοντέλο και αλλάζουν καθώς αλλάζει η κατάσταση του μοντέλου.

Εικόνα 1. Η αρχιτεκτονική μοντέλου / προβολής / ελεγκτή

Οφέλη του MVC

Η αρχιτεκτονική Model / View / Controller έχει πολλά οφέλη:

  • Υπάρχει ένας σαφώς καθορισμένος διαχωρισμός μεταξύ των στοιχείων ενός προγράμματος - προβλήματα σε κάθε τομέα μπορούν να επιλυθούν ανεξάρτητα.
  • Υπάρχει ένα καλά καθορισμένο API - οτιδήποτε χρησιμοποιεί το API σωστά μπορεί να αντικαταστήσει είτε το μοντέλο, την προβολή είτε τον ελεγκτή.
  • Η δέσμευση μεταξύ του μοντέλου και της προβολής είναι δυναμική - συμβαίνει στο χρόνο εκτέλεσης και όχι στο χρόνο μεταγλώττισης.

Με την ενσωμάτωση της αρχιτεκτονικής MVC σε ένα σχέδιο, κομμάτια ενός προγράμματος μπορούν να σχεδιαστούν ξεχωριστά (και να σχεδιαστούν για να κάνουν τη δουλειά τους καλά) και στη συνέχεια να ενωθούν μαζί στο χρόνο εκτέλεσης. Εάν ένα στοιχείο αργότερα κριθεί ακατάλληλο, μπορεί να αντικατασταθεί χωρίς να επηρεαστεί τα άλλα κομμάτια. Αντιπαραβάλλετε αυτό το σενάριο με τη μονολιθική προσέγγιση που χαρακτηρίζει πολλά γρήγορα και βρώμικα προγράμματα Java. Συχνά ένα πλαίσιο περιέχει όλη την κατάσταση, χειρίζεται όλα τα συμβάντα, κάνει όλους τους υπολογισμούς και εμφανίζει το αποτέλεσμα. Έτσι, σε όλα εκτός από τα απλούστερα τέτοια συστήματα, η πραγματοποίηση αλλαγών μετά το γεγονός δεν είναι ασήμαντη.

Καθορισμός των μερών

Το μοντέλο είναι το αντικείμενο που αντιπροσωπεύει τα δεδομένα στο πρόγραμμα. Διαχειρίζεται τα δεδομένα και πραγματοποιεί όλους τους μετασχηματισμούς σε αυτά τα δεδομένα. Το μοντέλο δεν έχει συγκεκριμένη γνώση ούτε των ελεγκτών του ούτε των απόψεών του - δεν περιέχει εσωτερικές αναφορές σε κανένα. Αντίθετα, το ίδιο το σύστημα αναλαμβάνει την ευθύνη να διατηρεί συνδέσμους μεταξύ του μοντέλου και των απόψεών του και να ειδοποιεί τις απόψεις όταν αλλάζει το μοντέλο.

Η θέα είναι το αντικείμενο που διαχειρίζεται την οπτική απεικόνιση των δεδομένων που αντιπροσωπεύονται από το μοντέλο. Παράγει την οπτική αναπαράσταση του μοντέλου αντικειμένου και εμφανίζει τα δεδομένα στο χρήστη. Αλληλεπιδρά με το μοντέλο μέσω αναφοράς στο ίδιο το αντικείμενο του μοντέλου.

Ο ελεγκτής είναι το αντικείμενο που παρέχει τα μέσα για την αλληλεπίδραση του χρήστη με τα δεδομένα που αντιπροσωπεύει το μοντέλο. Παρέχει τα μέσα με τα οποία γίνονται αλλαγές, είτε στις πληροφορίες του μοντέλου είτε στην εμφάνιση της προβολής. Αλληλεπιδρά με το μοντέλο μέσω αναφοράς στο ίδιο το αντικείμενο του μοντέλου.

Σε αυτό το σημείο ένα συγκεκριμένο παράδειγμα μπορεί να είναι χρήσιμο. Εξετάστε ως παράδειγμα το σύστημα που περιγράφεται στην εισαγωγή.

Σχήμα 2. Τρισδιάστατο σύστημα οπτικοποίησης

Το κεντρικό κομμάτι του συστήματος είναι το μοντέλο της τρισδιάστατης σκηνής. Το μοντέλο είναι μια μαθηματική περιγραφή των κορυφών και των προσώπων που συνθέτουν τη σκηνή. Τα δεδομένα που περιγράφουν κάθε κορυφή ή πρόσωπο μπορούν να τροποποιηθούν (ίσως ως αποτέλεσμα της εισόδου του χρήστη ή μιας παραμόρφωσης σκηνής ή αλγόριθμου μορφοποίησης). Ωστόσο, δεν υπάρχει έννοια της οπτικής, της μεθόδου εμφάνισης (wireframe ή solid), της προοπτικής ή της πηγής φωτός. Το μοντέλο είναι μια καθαρή αναπαράσταση των στοιχείων που συνθέτουν τη σκηνή.

Το τμήμα του προγράμματος που μετατρέπει τα δεδομένα στο μοντέλο σε γραφική απεικόνιση είναι η προβολή. Η προβολή ενσωματώνει την πραγματική προβολή της σκηνής. Είναι η γραφική αναπαράσταση της σκηνής από μια συγκεκριμένη άποψη, υπό συγκεκριμένες συνθήκες φωτισμού.

Ο ελεγκτής γνωρίζει τι μπορεί να γίνει στο μοντέλο και εφαρμόζει το περιβάλλον εργασίας χρήστη που επιτρέπει την έναρξη αυτής της ενέργειας. Σε αυτό το παράδειγμα, ένας πίνακας ελέγχου εισαγωγής δεδομένων ενδέχεται να επιτρέπει στο χρήστη να προσθέτει, να τροποποιεί ή να διαγράφει κορυφές και πρόσωπα.

Παρατηρητής και παρατηρήσιμος

Η γλώσσα Java υποστηρίζει την αρχιτεκτονική MVC με δύο κατηγορίες:

  • Παρατηρητής: Κάθε αντικείμενο που επιθυμεί να ειδοποιηθεί όταν αλλάζει η κατάσταση ενός άλλου αντικειμένου.
  • Αισθητός: Οποιοδήποτε αντικείμενο του οποίου η κατάσταση μπορεί να παρουσιάζει ενδιαφέρον και στο οποίο ένα άλλο αντικείμενο μπορεί να δηλώσει ενδιαφέρον.

Αυτές οι δύο κατηγορίες μπορούν να χρησιμοποιηθούν για την εφαρμογή πολύ περισσότερο από την αρχιτεκτονική MVC. Είναι κατάλληλα για οποιοδήποτε σύστημα όπου τα αντικείμενα πρέπει να ειδοποιούνται αυτόματα για αλλαγές που συμβαίνουν σε άλλα αντικείμενα.

Συνήθως, το μοντέλο είναι ένας υποτύπος του Αισθητός και η προβολή είναι ένας υποτύπος του Παρατηρητής. Αυτές οι δύο κατηγορίες χειρίζονται τη λειτουργία αυτόματης ειδοποίησης του MVC. Παρέχουν το μηχανισμό με τον οποίο οι προβολές μπορούν να ειδοποιούνται αυτόματα για αλλαγές στο μοντέλο. Το αντικείμενο αναφέρεται στο μοντέλο τόσο στον ελεγκτή όσο και στην προβολή επιτρέπει την πρόσβαση σε δεδομένα του μοντέλου.

Παρατηρητές και παρατηρήσιμες λειτουργίες

Τα ακόλουθα είναι καταχωρίσεις κώδικα για τις παρατηρήσεις και τις παρατηρήσιμες συναρτήσεις:

Παρατηρητής

  • δημόσια άκυρη ενημέρωση (παρατηρήσιμο obs, Object obj)

    Κλήθηκε όταν έχει συμβεί μια αλλαγή στην κατάσταση του παρατηρήσιμου.

Αισθητός

  • δημόσιο άκυρο addObserver (Observer obs)

    Προσθέτει έναν παρατηρητή στην εσωτερική λίστα των παρατηρητών.

  • public void deleteObserver (παρατηρητής obs)

    Διαγράφει έναν παρατηρητή από την εσωτερική λίστα των παρατηρητών.

  • δημόσιο άκυρο διαγραφή Παρατηρητές ()

    Διαγράφει όλους τους παρατηρητές από την εσωτερική λίστα παρατηρητών.

  • δημόσια int countObservers ()

    Επιστρέφει τον αριθμό των παρατηρητών στην εσωτερική λίστα των παρατηρητών.

  • προστατευμένο κενό σύνολοΑλλαγή ()

    Ορίζει την εσωτερική σημαία που δείχνει ότι αυτό το παρατηρήσιμο έχει αλλάξει κατάσταση.

  • προστατευμένο κενό καθαρό Αλλαγή ()

    Διαγράφει την εσωτερική σημαία που δείχνει ότι αυτή η παρατηρήσιμη κατάσταση έχει αλλάξει.

  • δημόσια boolean έχει αλλάξει ()

    Επιστρέφει την τιμή boolean true εάν αυτή η παρατηρήσιμη κατάσταση έχει αλλάξει.

  • δημόσια άκυρη ειδοποίηση Παρατηρητές ()

    Ελέγχει την εσωτερική σημαία για να δει εάν το παρατηρήσιμο έχει αλλάξει κατάσταση και ειδοποιεί όλους τους παρατηρητές.

  • public void notifyObservers (Αντικείμενο obj)

    Ελέγχει την εσωτερική σημαία για να δει εάν το παρατηρήσιμο έχει αλλάξει κατάσταση και ειδοποιεί όλους τους παρατηρητές. Περνά το αντικείμενο που καθορίζεται στη λίστα παραμέτρων στο κοινοποιώ() μέθοδος του παρατηρητή.

Στη συνέχεια θα ρίξουμε μια ματιά στον τρόπο δημιουργίας ενός νέου Αισθητός και Παρατηρητής τάξη και πώς να συνδέσουμε τα δύο μαζί.

Επεκτείνετε ένα παρατηρήσιμο

Δημιουργείται μια νέα κατηγορία παρατηρήσιμων αντικειμένων με την επέκταση της κλάσης Αισθητός. Επειδή τάξη Αισθητός ήδη εφαρμόζει όλες τις μεθόδους που είναι απαραίτητες για την παροχή της επιθυμητής συμπεριφοράς, η παράγωγη τάξη χρειάζεται να παρέχει μόνο κάποιο μηχανισμό για ρύθμιση και πρόσβαση στην εσωτερική κατάσταση του παρατηρήσιμου αντικειμένου.

Στο Παρατηρήσιμη τιμή Παρακάτω αναφέρεται, η εσωτερική κατάσταση του μοντέλου καταγράφεται από τον ακέραιο ν. Αυτή η τιμή είναι προσβάσιμη (και, το πιο σημαντικό, τροποποιείται) μόνο μέσω δημόσιων προσβατών. Εάν η τιμή αλλάξει, το παρατηρήσιμο αντικείμενο επικαλείται τη δική του σετ Αλλαγή () μέθοδος για να δείξει ότι η κατάσταση του μοντέλου έχει αλλάξει. Στη συνέχεια επικαλείται τη δική του ειδοποίησηObservers () μέθοδο για την ενημέρωση όλων των καταχωρημένων παρατηρητών.

Λίστα 1. Παρατηρήσιμη τιμή

 εισαγωγή java.util.Observable; δημόσια τάξη ObservableValue επεκτείνεται Observable {private int n = 0; δημόσια ObservableValue (int n) {this.n = n; } public void setValue (int n) {this.n = n; setChanged (); ειδοποίησηObservers (); } δημόσια int getValue () {return n; }} 

Εφαρμόστε έναν παρατηρητή

Δημιουργείται μια νέα κατηγορία αντικειμένων που παρατηρούν τις αλλαγές στην κατάσταση ενός άλλου αντικειμένου με την εφαρμογή του Παρατηρητής διεπαφή. ο Παρατηρητής διεπαφή απαιτεί ότι ένα εκσυγχρονίζω() μέθοδος παρέχεται στη νέα τάξη. ο εκσυγχρονίζω() Η μέθοδος καλείται κάθε φορά που η παρατηρήσιμη κατάσταση αλλάζει και ανακοινώνει αυτό το γεγονός καλώντας την ειδοποίησηObservers () μέθοδος. Ο παρατηρητής θα πρέπει στη συνέχεια να ανακρίνει το παρατηρήσιμο αντικείμενο για να προσδιορίσει τη νέα του κατάσταση και, στην περίπτωση της αρχιτεκτονικής MVC, να προσαρμόσει κατάλληλα την προβολή του.

Στα ακόλουθα TextObserver λίστα, το κοινοποιώ() Η μέθοδος ελέγχει πρώτα για να διασφαλίσει ότι το παρατηρήσιμο που έχει ανακοινώσει μια ενημέρωση είναι το παρατηρήσιμο που παρατηρεί αυτός ο παρατηρητής. Εάν είναι, τότε διαβάζει την κατάσταση του παρατηρήσιμου και εκτυπώνει τη νέα τιμή.

Λίστα 2. TextObserver

 εισαγωγή java.util.Observer; εισαγωγή java.util.Observable; δημόσια τάξη TextObserver εφαρμόζει το Observer {private ObservableValue ov = null; δημόσιο TextObserver (ObservableValue ov) {this.ov = ov; } δημόσια ακύρωση ενημέρωσης (παρατηρήσιμο obs, Object obj) {if (obs == ov) {System.out.println (ov.getValue ()); }}} 

Δέστε τα δύο μαζί

Ένα πρόγραμμα ειδοποιεί ένα παρατηρήσιμο αντικείμενο που ένας παρατηρητής επιθυμεί να ειδοποιηθεί για αλλαγές στην κατάστασή του καλώντας το παρατηρήσιμο αντικείμενο addObserver () μέθοδος. ο addObserver () Η μέθοδος προσθέτει τον παρατηρητή στον εσωτερικό κατάλογο των παρατηρητών που πρέπει να ειδοποιηθούν εάν αλλάξει η κατάσταση του παρατηρήσιμου.

Το παρακάτω παράδειγμα, που δείχνει την κλάση Main, δείχνει τον τρόπο χρήσης του addObserver () μέθοδος για να προσθέσετε μια παρουσία του TextObserver τάξη (Λίστα 2) στην παρατηρήσιμη λίστα που διατηρείται από το Παρατηρήσιμη τιμή τάξη (Λίστα 1).

Λίστα 3. addObserver ()

 δημόσια τάξη Main {public Main () {ObservableValue ov = new ObservableValue (0); TextObserver σε = νέο TextObserver (ov); ov.addObserver (έως); } δημόσιος στατικός κενός κενός (String [] args) {Main m = new Main (); }} 

Πώς λειτουργούν όλα μαζί

Η ακόλουθη ακολουθία συμβάντων περιγράφει πώς η αλληλεπίδραση μεταξύ ενός παρατηρήσιμου και ενός παρατηρητή συμβαίνει συνήθως μέσα σε ένα πρόγραμμα.

  1. Πρώτα ο χρήστης χειρίζεται ένα στοιχείο διεπαφής χρήστη που αντιπροσωπεύει έναν ελεγκτή. Ο ελεγκτής κάνει μια αλλαγή στο μοντέλο μέσω μιας δημόσιας μεθόδου πρόσβασης - δηλαδή setValue () στο παραπάνω παράδειγμα.
  2. Η μέθοδος του δημόσιου προσβάτη τροποποιεί τα ιδιωτικά δεδομένα, προσαρμόζει την εσωτερική κατάσταση του μοντέλου και τα ονομάζει σετ Αλλαγή () μέθοδος για να δείξει ότι η κατάστασή του έχει αλλάξει. Στη συνέχεια καλεί ειδοποίησηObservers () να ειδοποιήσει τους παρατηρητές ότι έχει αλλάξει. Η κλήση προς ειδοποίησηObservers () θα μπορούσε επίσης να εκτελεστεί αλλού, όπως σε ένα βρόχο ενημέρωσης που εκτελείται σε άλλο νήμα.
  3. ο εκσυγχρονίζω() Οι μέθοδοι σε κάθε έναν από τους παρατηρητές καλούνται, υποδεικνύοντας ότι έχει συμβεί μια αλλαγή στην κατάσταση. Οι παρατηρητές έχουν πρόσβαση στα δεδομένα του μοντέλου μέσω των δημόσιων μεθόδων πρόσβασης του μοντέλου και ενημερώνουν τις αντίστοιχες απόψεις τους.

Παρατηρητής / Παρατηρήσιμος σε αρχιτεκτονική MVC

Τώρα ας δούμε ένα παράδειγμα που δείχνει πώς τα παρατηρήσιμα και οι παρατηρητές λειτουργούν συνήθως μαζί σε μια αρχιτεκτονική MVC. Όπως το μοντέλο στο Παρατηρήσιμη τιμή (Λίστα 1) το μοντέλο σε αυτό το παράδειγμα είναι πολύ απλό. Η εσωτερική του κατάσταση αποτελείται από μία ακέραια τιμή. Η κατάσταση χειραγωγείται αποκλειστικά μέσω μεθόδων πρόσβασης όπως αυτές του Παρατηρήσιμη τιμή. Ο κωδικός για το μοντέλο βρίσκεται εδώ.

Αρχικά, γράφτηκε μια απλή κλάση προβολής κειμένου / ελεγκτή. Η τάξη συνδυάζει τις δυνατότητες τόσο μιας προβολής (εμφανίζει με κείμενο την τιμή της τρέχουσας κατάστασης του μοντέλου) όσο και ενός ελεγκτή (επιτρέπει στον χρήστη να εισαγάγει μια νέα τιμή για την κατάσταση του μοντέλου). Ο κωδικός βρίσκεται εδώ.

Σχεδιάζοντας το σύστημα χρησιμοποιώντας την αρχιτεκτονική MVC (αντί να ενσωματώσει τον κώδικα για το μοντέλο, την προβολή και τον ελεγκτή κειμένου σε μία μονολιθική κλάση), το σύστημα επανασχεδιάζεται εύκολα για να χειριστεί μια άλλη προβολή και έναν άλλο ελεγκτή. Σε αυτήν την περίπτωση, γράφτηκε μια τάξη προβολής / ρυθμιστή. Η θέση του ρυθμιστικού αντιπροσωπεύει την τιμή της τρέχουσας κατάστασης του μοντέλου και μπορεί να ρυθμιστεί από τον χρήστη για να ορίσει μια νέα τιμή για την κατάσταση του μοντέλου. Ο κωδικός βρίσκεται εδώ.

Σχετικά με τον Συγγραφέα

Ο Todd Sundsted γράφει προγράμματα από τότε που οι υπολογιστές έγιναν διαθέσιμοι σε μοντέλα επιτραπέζιων υπολογιστών. Αν και αρχικά ενδιαφερόταν να δημιουργήσει κατανεμημένες εφαρμογές αντικειμένων στο C ++, ο Todd μετακόμισε στη γλώσσα προγραμματισμού Java όταν η Java έγινε η προφανής επιλογή για κάτι τέτοιο.

Αυτή η ιστορία, "Observer and Observable" δημοσιεύθηκε αρχικά από την JavaWorld.