Για να χρησιμοποιήσετε σωστά τα μοτίβα κατάστασηκαι Στρατηγικήστον πυρήνα των εφαρμογών Java, είναι σημαντικό για τους προγραμματιστές Java να κατανοήσουν ξεκάθαρα τη διαφορά μεταξύ των δύο. Παρόλο που και τα δύο πρότυπα κατάστασης και στρατηγικής έχουν παρόμοια δομή και και τα δύο βασίζονται στην αρχή ανοιχτού/κλειστού που αντιπροσωπεύει το "O" στις αρχές SOLID, είναι εντελώς διαφορετικά σε προθέσεις. πρότυπο Στρατηγικήστην Java χρησιμοποιείται για ενθυλάκωσησχετικά σύνολα αλγορίθμων για την παροχή ευελιξίας εκτέλεσης στον πελάτη. Ο πελάτης μπορεί να επιλέξει οποιονδήποτε αλγόριθμο κατά την εκτέλεση χωρίς να αλλάξει το περιβάλλον της κλάσης που χρησιμοποιεί το αντικείμενο Strategy. Μερικά δημοφιλή παραδείγματα μοτίβων Στρατηγικήείναι η σύνταξη κώδικα που χρησιμοποιεί αλγόριθμους όπως κρυπτογράφηση, συμπίεση ή ταξινόμηση. Από την άλλη πλευρά, το πρότυπο κατάστασης επιτρέπει σε ένα αντικείμενο να συμπεριφέρεται διαφορετικά σε διαφορετικές καταστάσεις. Γιατί στον πραγματικό κόσμο ένα αντικείμενο συχνά έχει καταστάσεις και συμπεριφέρεται διαφορετικά μέσα διαφορετικά κράτηπ.χ. ένα μηχάνημα αυτόματης πώλησης πουλά αγαθά μόνο αν είναι σε κατάσταση hasCoin, δεν πουλά μέχρι να του βάλεις ένα νόμισμα. Τώρα μπορείτε να δείτε ξεκάθαρα τη διαφορά μεταξύ της στρατηγικής και των προτύπων κράτους, είναι διαφορετικές προθέσεις. Το μοτίβο κατάστασης βοηθά ένα αντικείμενο να διαχειριστεί την κατάσταση, ενώ το μοτίβο στρατηγικής επιτρέπει στον πελάτη να επιλέξει μια διαφορετική συμπεριφορά. Μια άλλη διαφορά που δεν είναι τόσο εύκολο να δει κανείς είναι ποιος διαχειρίζεται την αλλαγή στη συμπεριφορά. Στην περίπτωση του σχεδίου στρατηγικής, είναι ο πελάτης που παρέχει διαφορετικές στρατηγικές στο πλαίσιο, στο πρότυπο κατάστασης, η μετάβαση διαχειρίζεται το πλαίσιο ή την κατάσταση του ίδιου του αντικειμένου. Επιπλέον, εάν διαχειρίζεστε οι ίδιοι τις αλλαγές κατάστασης στο αντικείμενο State, πρέπει να υπάρχει αναφορά στο περιβάλλον, για παράδειγμα, σε έναν αυτόματο πωλητή πρέπει να είναι δυνατή η κλήση της μεθόδου setState() για να αλλάξετε την τρέχουσα κατάσταση του περιβάλλοντος. Από την άλλη πλευρά, το αντικείμενο Στρατηγική δεν περιέχει ποτέ αναφορά στο πλαίσιο, ο ίδιος ο πελάτης μεταβιβάζει τη Στρατηγική της επιλογής του στο πλαίσιο. Η διαφορά μεταξύ των μοτίβων κατάστασης και στρατηγικής είναι μια από τις δημοφιλείς ερωτήσεις συνέντευξης σχετικά με τα μοτίβα Java, σε αυτό το άρθρο σχετικά με τα μοτίβα Java θα το δούμε πιο προσεκτικά. Θα διερευνήσουμε ορισμένες από τις ομοιότητες και τις διαφορές μεταξύ των μοτίβων στρατηγικής και κατάστασης στην Java για να σας βοηθήσουμε να βελτιώσετε την κατανόησή σας για αυτά τα μοτίβα.

Ομοιότητες μεταξύ προτύπων κράτους και στρατηγικής

Αν κοιτάξετε το διάγραμμα UML των μοτίβων κατάστασης και στρατηγικής, θα παρατηρήσετε ότι και τα δύο μοιάζουν μεταξύ τους. Ένα αντικείμενο που χρησιμοποιεί μια κατάσταση για να αλλάξει τη συμπεριφορά του είναι γνωστό ως αντικείμενο περιβάλλοντος, ομοίως ένα αντικείμενο που χρησιμοποιεί μια στρατηγική για να αλλάξει τη συμπεριφορά του είναι γνωστό ως αντικείμενο περιβάλλοντος. Θυμηθείτε ότι ο πελάτης αλληλεπιδρά με το αντικείμενο Context. Στην περίπτωση του σχεδίου κατάστασης, το περιβάλλον εκχωρεί μεθόδους κλήσης στο αντικείμενο κατάστασης, το οποίο διατηρείται ως τρέχον αντικείμενο, ενώ στην περίπτωση του μοτίβου στρατηγικής, το περιβάλλον χρησιμοποιεί το αντικείμενο στρατηγικής ως παράμετρο ή παρέχεται κατά τη δημιουργία του πλαισίου του αντικειμένου. Διάγραμμα μοτίβου κατάστασης UML σε Java
Αυτό το διάγραμμα UML για το μοτίβο κατάστασης απεικονίζει το κλασικό πρόβλημα της δημιουργίας ενός αντικειμενοστρεφούς σχεδίου μηχανήματος αυτόματης πώλησης σε Java. Μπορείτε να δείτε ότι η κατάσταση του μηχανήματος αυτόματης πώλησης αναπαρίσταται χρησιμοποιώντας μια διεπαφή, η οποία στη συνέχεια έχει μια υλοποίηση για την αναπαράσταση μιας συγκεκριμένης κατάστασης. Κάθε κατάσταση έχει επίσης αναφορές στο περιβάλλον του αντικειμένου για να γίνει η μετάβαση σε άλλη κατάσταση ως αποτέλεσμα ενεργειών που επικαλούνται το περιβάλλον.
Αυτό το διάγραμμα UML για το μοτίβο στρατηγικής περιέχει λειτουργικές υλοποιήσεις του είδους. Επειδή υπάρχουν πολλοί αλγόριθμοι ταξινόμησης, αυτό το μοτίβο σχεδίασης επιτρέπει στον πελάτη να επιλέξει έναν αλγόριθμο κατά την ταξινόμηση αντικειμένων. στην πραγματικότητα Πλαίσιο συλλογής Javaκάνει χρήση αυτού του μοτίβου εφαρμόζοντας τη μέθοδο Collections.sort(), η οποία χρησιμοποιείται για την ταξινόμηση αντικειμένων στην Java. Η μόνη διαφορά είναι ότι αντί να επιτρέπει στον πελάτη να επιλέξει έναν αλγόριθμο ταξινόμησης, επιτρέπει στον πελάτη να καθορίσει μια στρατηγική σύγκρισης περνώντας μια παρουσία της διεπαφής σύγκρισης ή συγκρίσιμης διεπαφής σε Java . Ας δούμε μερικές ομοιότητες μεταξύ αυτών των δύο κύριων μοτίβων σχεδίασης στην Java:
  1. Και τα δύο μοτίβα, η κατάσταση και η στρατηγική, διευκολύνουν την προσθήκη νέας κατάστασης και στρατηγικής χωρίς να επηρεάζεται το περιβάλλον του αντικειμένου που τις χρησιμοποιεί.

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

  3. Ακριβώς όπως ένα περιβάλλον αντικειμένου ξεκινά με την κατάσταση αρχικοποίησης ενός αντικειμένου στο μοτίβο κατάστασης, ένα περιβάλλον αντικειμένου έχει επίσης μια προεπιλεγμένη στρατηγική στην περίπτωση του μοτίβου στρατηγικής στην Java.

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

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

Διαφορές μεταξύ μοτίβων στρατηγικής και κατάστασης στην Java

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

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

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

  4. Η υλοποίηση της Στρατηγικής μπορεί να περάσει ως παράμετρος στο αντικείμενο που θα τη χρησιμοποιήσει, για παράδειγμα η Collection.sort() παίρνει έναν Συγκριτικό που είναι η στρατηγική. Από την άλλη πλευρά, η κατάσταση είναι μέρος του ίδιου του περιβάλλοντος του αντικειμένου και με την πάροδο του χρόνου, το περιβάλλον του αντικειμένου μεταβαίνει από τη μια κατάσταση στην άλλη.

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

  6. Μια άλλη θεωρητική διαφορά μεταξύ των μοτίβων στρατηγικής και κατάστασης είναι ότι ο δημιουργός ορίζει το τμήμα «Πώς» του αντικειμένου, για παράδειγμα, «Πώς» το αντικείμενο ταξινόμησης ταξινομεί τα δεδομένα, από την άλλη πλευρά, το μοτίβο κατάστασης ορίζει το «τι» και "when" μέρη στο αντικείμενο, για παράδειγμα, τι μπορεί να κάνει ένα αντικείμενο όταν βρίσκεται σε μια συγκεκριμένη κατάσταση.

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

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

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

Πρόκειται για διαφορά μεταξύ των μοτίβων κατάστασης και στρατηγικής στην Java. Όπως είπα, και τα δύο φαίνονται παρόμοια στις κλάσεις τους και στα διαγράμματα UML, και τα δύο παρέχουν μια αρχή ανοιχτού/κλειστού και ενσωματώνουν τη συμπεριφορά. Χρησιμοποιήστε το μοτίβο στρατηγικής για να ενσωματώσετε έναν αλγόριθμο ή μια στρατηγική που παρέχεται σε ένα περιβάλλον κατά το χρόνο εκτέλεσης, ίσως ως παράμετρος ή σύνθετο αντικείμενο, και χρησιμοποιήστε το μοτίβο κατάστασης για να ελέγξετε τις μεταβάσεις καταστάσεων στην Java. Πρωτότυπο "ΜοτίβοΚατάσταση"Πηγή .ru

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

Προϋποθέσεις, Εργασία, Ραντεβού

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

Κίνητρο

Σκεφτείτε την τάξη TCPConnection, που παρουσιάζει σύνδεση δικτύου. Ένα αντικείμενο αυτής της κλάσης μπορεί να βρίσκεται σε μία από πολλές καταστάσεις: Καθιερωμένος(εγκατεστημένο) ακούγοντας(ακούγοντας), κλειστό(κλειστό). Όταν το αντικείμενο TCPConnectionλαμβάνει αιτήματα από άλλα αντικείμενα και, στη συνέχεια, ανάλογα με την τρέχουσα κατάσταση, ανταποκρίνεται διαφορετικά. Για παράδειγμα, μια απάντηση σε ένα αίτημα Άνοιξε(ανοιχτό) εξαρτάται από το αν η σύνδεση είναι σε κατάσταση κλειστόή Καθιερωμένος. Το πρότυπο κατάστασης περιγράφει πώς ένα αντικείμενο TCPConnectionμπορεί να συμπεριφέρονται διαφορετικά όταν βρίσκονται σε διαφορετικές καταστάσεις. source.ru

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

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

ιστοσελίδα αρχική πηγή

Τάξη TCPConnectionαποθηκεύει ένα αντικείμενο κατάστασης (ένα παράδειγμα μιας υποκλάσης TCPSstate) που αντιπροσωπεύει την τρέχουσα κατάσταση της σύνδεσης και εκχωρεί όλα τα αιτήματα για συγκεκριμένες καταστάσεις σε αυτό το αντικείμενο. TCPConnectionχρησιμοποιεί το δικό του παράδειγμα υποκλάσης TCPSstateαρκετά απλό: καλώντας τις μεθόδους της ενοποιημένης διεπαφής TCPSstate, μόνο ανάλογα με το ποια αυτή τη στιγμήαποθηκεύεται μια συγκεκριμένη υποκατηγορία TCPSstate-α - το αποτέλεσμα είναι διαφορετικό, δηλ. Στην πραγματικότητα, εκτελούνται λειτουργίες που είναι συγκεκριμένες για αυτήν την κατάσταση σύνδεσης. Πηγή original.ru

Και κάθε φορά που αλλάζει η κατάσταση σύνδεσηςTCPConnectionαλλάζει το αντικείμενο κατάστασης του. Για παράδειγμα, όταν μια εγκατεστημένη σύνδεση είναι κλειστή, TCPConnectionαντικαθιστά ένα στιγμιότυπο μιας κλάσης Το TCPE ιδρύθηκεπαράδειγμα TCPΚλειστό. ιστοσελίδα αρχική πηγή

Σημάδια εφαρμογής, χρήση του προτύπου State (State)

Χρησιμοποιήστε το μοτίβο κατάστασης στις ακόλουθες περιπτώσεις: πηγή original.ru
  1. Όταν η συμπεριφορά ενός αντικειμένου εξαρτάται από την κατάστασή του και πρέπει να αλλάξει κατά το χρόνο εκτέλεσης. .ru
  2. Όταν υπάρχουν λειτουργίες πολλαπλών διακλαδώσεων στο opcode δηλώσεις υπό όρους, στο οποίο η επιλογή κλάδου εξαρτάται από το κράτος. Τυπικά, σε αυτή την περίπτωση, η κατάσταση αντιπροσωπεύεται από απαριθμημένες σταθερές. Συχνά η ίδια δομή εντολών υπό όρους επαναλαμβάνεται σε πολλαπλές εντολές.Το μοτίβο κατάστασης προτείνει κάθε κλάδο να τοποθετηθεί σε ξεχωριστή κλάση. Αυτό επιτρέπει σε κάποιον να αντιμετωπίζει την κατάσταση ενός αντικειμένου ως ένα ανεξάρτητο αντικείμενο που μπορεί να αλλάξει ανεξάρτητα από άλλα. πηγή original.ru

Λύση

Πηγή ιστότοπου πρωτότυπος ιστότοπος

original.ru

Συμμετέχοντες του κρατικού προτύπου

πηγή original.ru
  1. Συμφραζόμενα(TCPConnection) - πλαίσιο.
    Καθορίζει μια ενιαία διεπαφή για πελάτες.
    Αποθηκεύει ένα στιγμιότυπο μιας υποκλάσης ConcreteState, το οποίο καθορίζει την τρέχουσα κατάσταση. original.ru
  2. κατάσταση(TCPSstate) - κατάσταση.
    Καθορίζει μια διεπαφή για την ενθυλάκωση της συμπεριφοράς που σχετίζεται με μια συγκεκριμένη κατάσταση ενός Περιεχομένου. πηγή original.ru
  3. Υποκατηγορίες ConcreteState(TCPEstablished, TCPListen, TCPClosed) - συγκεκριμένη κατάσταση.
    Κάθε υποκλάση υλοποιεί μια συμπεριφορά που σχετίζεται με κάποια κατάσταση περιβάλλοντος. Συμφραζόμενα. αρχική πηγή του ιστότοπου

Σχέδιο χρήσης του σχεδίου κατάστασης

Τάξη Συμφραζόμεναμεταβιβάζει αιτήματα στο τρέχον αντικείμενο ConcreteState. αρχική πηγή του ιστότοπου

Το πλαίσιο μπορεί να περάσει ως όρισμα σε ένα αντικείμενο κατάστασηΑυτός που θα επεξεργαστεί το αίτημα. Αυτό επιτρέπει στο αντικείμενο κατάστασης ( ConcreteState) πρόσβαση στο πλαίσιο εάν είναι απαραίτητο. ιστοσελίδα αρχική πηγή

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

Ταυτόχρονα, είτε Συμφραζόμενα, ή τις ίδιες τις υποκατηγορίες ConcreteStateμπορεί να αποφασίσει υπό ποιες προϋποθέσεις και με ποια σειρά επέρχεται η αλλαγή των καταστάσεων. Πηγή .ru

Ερωτήσεις σχετικά με την εφαρμογή του κρατικού προτύπου

Ερωτήσεις σχετικά με την εφαρμογή του κρατικού προτύπου: Πηγή original.ru
  1. Τι καθορίζει τις μεταβάσεις μεταξύ των κρατών.
    Το πρότυπο κατάστασης δεν λέει τίποτα σχετικά με το ποιος συμμετέχων καθορίζει τις προϋποθέσεις (κριτήρια) για τη μετάβαση μεταξύ των καταστάσεων. Εάν τα κριτήρια είναι σταθερά, τότε μπορούν να εφαρμοστούν απευθείας στην τάξη Συμφραζόμενα. Ωστόσο, σε γενικές γραμμές, πιο ευέλικτο και η σωστή προσέγγισηείναι να αφήσουμε τις ίδιες τις υποκλάσεις της τάξης κατάστασηκαθορίσει την επόμενη κατάσταση και μεταβατική στιγμή. Για αυτό στην τάξη Συμφραζόμεναπρέπει να προσθέσετε μια διεπαφή που επιτρέπει από αντικείμενα κατάστασηορίσει την κατάστασή του.
    Αυτή η αποκεντρωμένη λογική μετάβασης είναι ευκολότερο να τροποποιηθεί και να επεκταθεί - απλά πρέπει να ορίσετε νέες υποκλάσεις κατάσταση. Το μειονέκτημα της αποκέντρωσης είναι ότι κάθε υποκατηγορία κατάστασηπρέπει να «γνωρίζει» τουλάχιστον μία ακόμη υποκλάση μιας άλλης κατάστασης (στην οποία μπορεί πραγματικά να αλλάξει την τρέχουσα κατάσταση), η οποία εισάγει εξαρτήσεις υλοποίησης μεταξύ υποκλάσεων. source.ru

    Πηγή ιστότοπου πρωτότυπος ιστότοπος
  2. Επιτραπέζιο εναλλακτικό.
    Υπάρχει ένας άλλος τρόπος για τη δομή του κώδικα που βασίζεται σε κατάσταση. Αυτή είναι η αρχή μιας μηχανής πεπερασμένης κατάστασης. Χρησιμοποιεί έναν πίνακα για να αντιστοιχίσει την είσοδο σε μεταβάσεις κατάστασης. Με τη βοήθειά του, μπορείτε να προσδιορίσετε σε ποια κατάσταση θέλετε να μεταβείτε όταν φτάνουν κάποια δεδομένα εισόδου. Στην ουσία, με αυτόν τον τρόπο, αντικαθιστούμε τον υπό όρους κωδικό με αναζήτηση πίνακα.
    Το κύριο πλεονέκτημα του αυτόματου είναι η κανονικότητά του: για να αλλάξετε τα κριτήρια μετάβασης, αρκεί να τροποποιήσετε μόνο τα δεδομένα, όχι τον κωδικό. Υπάρχουν όμως και μειονεκτήματα:
    - οι αναζητήσεις πινάκων είναι συχνά λιγότερο αποτελεσματικές από τις κλήσεις συναρτήσεων,
    - η παρουσίαση της λογικής μετάβασης σε ομοιόμορφη μορφή πίνακα καθιστά τα κριτήρια λιγότερο σαφή και, επομένως, πιο δυσνόητα,
    - είναι συνήθως δύσκολο να προστεθούν ενέργειες που συνοδεύουν τις μεταβάσεις κατάστασης. Η μέθοδος του πίνακα λαμβάνει υπόψη τις καταστάσεις και τις μεταβάσεις μεταξύ τους, αλλά πρέπει να επεκταθεί έτσι ώστε να μπορούν να εκτελούνται αυθαίρετοι υπολογισμοί με κάθε αλλαγή κατάστασης.
    Η κύρια διαφορά μεταξύ των μηχανών κατάστασης που βασίζονται σε πίνακα και του σχεδίου κατάστασης μπορεί να συνοψιστεί ως εξής: Το πρότυπο κατάστασης μοντελοποιεί συμπεριφορά εξαρτώμενη από την κατάσταση, ενώ μέθοδος πίνακαδίνει έμφαση στον ορισμό των μεταβάσεων μεταξύ των κρατών. Πηγή original.ru

    source.ru πρωτότυπο
  3. Δημιουργία και καταστροφή κρατικών αντικειμένων.
    Κατά τη διαδικασία ανάπτυξης, συνήθως πρέπει να επιλέξετε μεταξύ:
    - δημιουργία αντικειμένων κατάστασης όταν χρειάζονται και καταστροφή αμέσως μετά τη χρήση,
    - δημιουργώντας τα εκ των προτέρων και για πάντα.

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

    Πηγή ιστότοπου πρωτότυπος ιστότοπος
  4. Χρήση δυναμικής αλλαγής.
    Μπορείτε να αλλάξετε τη συμπεριφορά κατά απαίτηση αλλάζοντας την κλάση ενός αντικειμένου κατά το χρόνο εκτέλεσης, αλλά αυτό δεν υποστηρίζεται στις περισσότερες αντικειμενοστρεφείς γλώσσες. Η εξαίρεση είναι η Perl, η JavaScript και άλλες γλώσσες που βασίζονται σε σενάρια, οι οποίες παρέχουν έναν τέτοιο μηχανισμό και επομένως διατηρούν απευθείας την κατάσταση μοτίβου. Αυτό επιτρέπει στα αντικείμενα να αλλάζουν τη συμπεριφορά τους αλλάζοντας τον κωδικό κλάσης τους. source.ru πρωτότυπο

    αρχική πηγή.ru

Αποτελέσματα

Αποτελέσματα της χρήσης κατάσταση προτύπου: Πηγή original.ru
  1. Εντοπίζει τη συμπεριφορά συγκεκριμένης κατάστασης.
    Και το χωρίζει σε μέρη που αντιστοιχούν σε καταστάσεις. Το πρότυπο κατάστασης τοποθετεί όλη τη συμπεριφορά που σχετίζεται με μια συγκεκριμένη κατάσταση ξεχωριστό αντικείμενο. Δεδομένου ότι ο εξαρτώμενος από την κατάσταση κώδικας βρίσκεται εξ ολοκλήρου σε μία από τις υποκατηγορίες της κλάσης κατάσταση, τότε μπορείτε να προσθέσετε νέες καταστάσεις και μεταβάσεις απλά δημιουργώντας νέες υποκλάσεις.
    Αντίθετα, θα μπορούσε κανείς να χρησιμοποιήσει μέλη δεδομένων για να ορίσει εσωτερικές καταστάσεις και στη συνέχεια τις λειτουργίες του αντικειμένου Συμφραζόμεναελέγξτε αυτά τα δεδομένα. Αλλά σε αυτήν την περίπτωση, παρόμοιες εντολές υπό όρους ή διακλαδώσεις θα είναι διάσπαρτες σε όλο τον κώδικα κλάσης. Συμφραζόμενα. Ταυτόχρονα, η προσθήκη μιας νέας κατάστασης θα απαιτούσε αλλαγή πολλών λειτουργιών, γεγονός που θα καθιστούσε δύσκολη τη συντήρηση. Το μοτίβο κατάστασης λύνει αυτό το πρόβλημα, αλλά δημιουργεί και ένα άλλο, καθώς η συμπεριφορά για διαφορετικές καταστάσεις κατανέμεται σε πολλές υποκατηγορίες. κατάσταση. Αυτό αυξάνει τον αριθμό των τάξεων. Φυσικά, μια κατηγορία είναι πιο συμπαγής, αλλά αν υπάρχουν πολλές καταστάσεις, τότε μια τέτοια κατανομή είναι πιο αποτελεσματική, αφού διαφορετικά θα έπρεπε να αντιμετωπίσει δυσκίνητες προτάσεις υπό όρους.
    Η παρουσία δυσκίνητων δηλώσεων υπό όρους είναι ανεπιθύμητη, καθώς και η παρουσία μακρών διαδικασιών. Είναι πολύ μονολιθικοί, γι' αυτό η τροποποίηση και επέκταση κώδικα γίνεται πρόβλημα. Το πρότυπο κατάστασης προσφέρει έναν καλύτερο τρόπο δόμησης του εξαρτώμενου από το κράτος κώδικα. Η λογική που περιγράφει τις μεταβάσεις καταστάσεων δεν είναι πλέον τυλιγμένη σε μονολιθικές δηλώσεις ανή διακόπτης, αλλά κατανέμεται μεταξύ υποκατηγοριών κατάσταση. Με την ενθυλάκωση κάθε μετάβασης και δράσης σε μια τάξη, η κατάσταση γίνεται ένα πλήρες αντικείμενο. Αυτό βελτιώνει τη δομή του κώδικα και διευκρινίζει τον σκοπό του. πηγή original.ru
  2. Καθιστά σαφείς τις μεταβάσεις μεταξύ των καταστάσεων.
    Εάν ένα αντικείμενο ορίζει την τρέχουσα κατάστασή του αποκλειστικά με όρους εσωτερικών δεδομένων, τότε οι μεταβάσεις καταστάσεων δεν έχουν ρητή αναπαράσταση. εμφανίζονται μόνο ως εκχωρήσεις σε ορισμένες μεταβλητές. Η εισαγωγή χωριστών αντικειμένων για διαφορετικές καταστάσεις κάνει τις μεταβάσεις πιο σαφείς. Επιπλέον, αντικείμενα κατάστασημπορεί να προστατεύσει το πλαίσιο Συμφραζόμενααπό την αναντιστοιχία των εσωτερικών μεταβλητών, αφού οι μεταβάσεις από την άποψη του πλαισίου είναι ατομικές ενέργειες. Για να εφαρμόσετε τη μετάβαση, πρέπει να αλλάξετε την τιμή μόνο μιας μεταβλητής (μεταβλητή αντικειμένου κατάστασηστην τάξη Συμφραζόμενα) και όχι πολλά. Πηγή original.ru
  3. Τα αντικείμενα κατάστασης μπορούν να κοινοποιηθούν.
    Αν στο αντικείμενο κατάστασης κατάστασηδεν υπάρχουν μεταβλητές παρουσίας, δηλαδή η κατάσταση που αντιπροσωπεύει κωδικοποιείται αποκλειστικά από τον ίδιο τον τύπο, τότε διαφορετικά περιβάλλοντα μπορούν να μοιράζονται το ίδιο αντικείμενο κατάσταση. Όταν οι καταστάσεις διαχωρίζονται με αυτόν τον τρόπο, είναι ουσιαστικά flyweights (βλέπε μοτίβο flyweight) που δεν έχουν εσωτερική κατάσταση, μόνο συμπεριφορά. πηγή τοποθεσίας αρχικός ιστότοπος

Παράδειγμα

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

Πρώτα απ 'όλα, ας ορίσουμε την κλάση TCPConnection, το οποίο παρέχει μια διεπαφή για μεταφορά δεδομένων και χειρίζεται αιτήματα αλλαγής κατάστασης: TCPConnection . source.ru πρωτότυπο

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

Πηγή original.ru

TCPConnectionαναθέτει όλα τα αιτήματα που εξαρτώνται από το κράτος σε μια παρουσία που είναι αποθηκευμένη στην κατάσταση TCPSstate. Επιπλέον, στην τάξη TCPConnectionυπάρχει επέμβαση Αλλαγή Κατάστασης, το οποίο μπορεί να χρησιμοποιηθεί για την εγγραφή ενός δείκτη σε άλλο αντικείμενο σε αυτή τη μεταβλητή TCPSstate. Κατασκευαστής τάξης TCPConnectionαρχικοποιεί κατάστασηδείκτη προς την κατάσταση κλεισίματος TCPΚλειστό(θα το ορίσουμε παρακάτω). source.ru

πηγή τοποθεσίας αρχικός ιστότοπος

Κάθε επέμβαση TCPSstateπαίρνει ένα παράδειγμα TCPConnectionως παράμετρος, επιτρέποντας έτσι το αντικείμενο TCPSstateπρόσβαση σε δεδομένα αντικειμένου TCPConnectionκαι αλλάξτε την κατάσταση σύνδεσης. .ru

Στην τάξη TCPSstateεφάρμοσε την προεπιλεγμένη συμπεριφορά για όλα τα αιτήματα που του ανατέθηκαν. Μπορεί επίσης να αλλάξει την κατάσταση ενός αντικειμένου TCPConnectionμέσω της επέμβασης Αλλαγή Κατάστασης. TCPSstateβρίσκεται στην ίδια συσκευασία με TCPConnection, επομένως έχει επίσης πρόσβαση σε αυτήν τη λειτουργία: TCPState . αρχική πηγή του ιστότοπου

source.ru

Σε υποκατηγορίες TCPSstateεξαρτώμενη από το κράτος συμπεριφορά. Μια σύνδεση TCP μπορεί να είναι σε πολλές καταστάσεις: Καθιερωμένος(εγκατεστημένο) ακούγοντας(ακούγοντας), κλειστό(κλειστό) κ.λπ., και το καθένα από αυτά έχει τη δική του υποκατηγορία TCPSstate. Για απλότητα, θα εξετάσουμε λεπτομερώς μόνο 3 υποκατηγορίες - Το TCPE ιδρύθηκε, TCPListenκαι TCPΚλειστό. αρχική πηγή ιστότοπου

αρχική πηγή.ru

Σε υποκατηγορίες TCPSstateΗ συμπεριφορά που εξαρτάται από την κατάσταση εφαρμόζεται για εκείνα τα αιτήματα που είναι έγκυρα σε αυτήν την κατάσταση. Πηγή original.ru

αρχική πηγή ιστότοπου

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

αιτία Αλλαγή Κατάστασηςγια να αλλάξετε την κατάσταση ενός αντικειμένου TCPConnection. Ο ίδιος δεν έχει καμία πληροφορία για το πρωτόκολλο TCP. Είναι οι υποκατηγορίες TCPSstateορίστε τις μεταβάσεις κατάστασης και τις ενέργειες που υπαγορεύονται από το πρωτόκολλο. αρχική πηγή του ιστότοπου

Ru πρωτότυπο

Αξιοσημείωτες χρήσεις του προτύπου κατάστασης

Οι Ralph Johnson και Jonathan Zweig χαρακτηρίζουν το πρότυπο κατάστασης και το περιγράφουν σε σχέση με το πρωτόκολλο TCP.
Τα πιο δημοφιλή προγράμματα διαδραστικής σχεδίασης παρέχουν «εργαλεία» για την εκτέλεση λειτουργιών άμεσου χειρισμού. Για παράδειγμα, ένα εργαλείο σχεδίασης γραμμής επιτρέπει στο χρήστη να κάνει κλικ σε ένα αυθαίρετο σημείο με το ποντίκι και στη συνέχεια να σύρει το ποντίκι για να σχεδιάσει μια γραμμή από αυτό το σημείο. Το εργαλείο επιλογής σάς επιτρέπει να επιλέξετε ορισμένα σχήματα. Συνήθως όλα τα διαθέσιμα εργαλεία τοποθετούνται σε μια παλέτα. Η δουλειά του χρήστη είναι να επιλέγει και να εφαρμόζει ένα εργαλείο, αλλά η πραγματική συμπεριφορά του επεξεργαστή ποικίλλει όταν αλλάζει εργαλεία: με το εργαλείο σχεδίασης δημιουργούμε σχήματα, με το εργαλείο επιλογής τα επιλέγουμε κ.λπ. Πηγή original.ru

Για να αντικατοπτρίσετε την εξάρτηση της συμπεριφοράς του επεξεργαστή από το τρέχον εργαλείο, μπορείτε να χρησιμοποιήσετε το μοτίβο κατάστασης. αρχική πηγή του ιστότοπου

Μπορείτε να ορίσετε μια αφηρημένη κλάση ΕργαλείοΈνα του οποίου οι υποκατηγορίες εφαρμόζουν συμπεριφορά για συγκεκριμένο εργαλείο. Το πρόγραμμα επεξεργασίας γραφικών διατηρεί έναν σύνδεσμο προς το τρέχον αντικείμενο Πολύμεγάλοκαι αναθέτει σε αυτήν εισερχόμενα αιτήματα. Όταν επιλέγεται ένα εργαλείο, ο επεξεργαστής χρησιμοποιεί ένα διαφορετικό αντικείμενο, το οποίο οδηγεί σε αλλαγή συμπεριφοράς. source.ru

Αυτή η τεχνική χρησιμοποιείται σε πλαίσια συντάκτες γραφικών HotDraw και Unidraw. Επιτρέπει στους πελάτες να ορίζουν εύκολα νέα είδη εργαλείων. ΣΤΟ HotDrawΤάξη DrawingControllerανακατευθύνει αιτήματα στο τρέχον αντικείμενο Εργαλείο. ΣΤΟ Unidrawκαλούνται οι αντίστοιχες κλάσεις Θεατήςκαι Εργαλείο. Το παρακάτω διάγραμμα κλάσεων είναι μια σχηματική αναπαράσταση των διεπαφών κλάσεων Εργαλείο

Πηγή ιστότοπου πρωτότυπος ιστότοπος

Ο σκοπός του κρατικού προτύπου

  • Το πρότυπο κατάστασης επιτρέπει σε ένα αντικείμενο να αλλάξει τη συμπεριφορά του με βάση την εσωτερική του κατάσταση. Φαίνεται ότι το αντικείμενο έχει αλλάξει την κλάση του.
  • Το μοτίβο κατάστασης είναι μια αντικειμενοστραφής υλοποίηση μιας μηχανής κατάστασης.

Το πρόβλημα επιλύεται

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

Συζήτηση προτύπων κατάστασης

Το πρότυπο κατάστασης λύνει αυτό το πρόβλημα με τον ακόλουθο τρόπο:

  • Παρουσιάζει την κλάση Context, η οποία ορίζει μια διεπαφή με τον έξω κόσμο.
  • Εισάγει την αφηρημένη τάξη Κατάσταση .
  • Αντιπροσωπεύει τις διάφορες «καταστάσεις» μιας κρατικής μηχανής ως υποκατηγορίες του κράτους.
  • Η κλάση Context έχει έναν δείκτη στην τρέχουσα κατάσταση που αλλάζει όταν αλλάζει η κατάσταση της μηχανής κατάστασης.

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

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

Η δομή του κρατικού προτύπου

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

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

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

Χρησιμοποιώντας το μοτίβο κατάστασης

  • Ορίστε μια υπάρχουσα ή δημιουργήστε μια νέα κλάση περιβάλλοντος "wrapper" που θα χρησιμοποιηθεί από τον πελάτη ως "μηχανή κατάστασης".
  • Δημιουργήστε μια βασική κλάση κατάστασης που μιμείται τη διεπαφή της κλάσης Context. Κάθε μέθοδος παίρνει μια πρόσθετη παράμετρο: μια παρουσία της κλάσης Context. Η κλάση State μπορεί να ορίσει οποιαδήποτε χρήσιμη συμπεριφορά "προεπιλογής".
  • Εξαγωγή κλάσεων από κατάσταση για όλες τις πιθανές καταστάσεις.
  • Το Context της κλάσης "wrapper" έχει μια αναφορά στο αντικείμενο "τρέχουσα κατάσταση".
  • Η κλάση Context απλώς αναθέτει όλα τα αιτήματα που λαμβάνονται από τον πελάτη στο αντικείμενο "τρέχουσα κατάσταση", ενώ μεταβιβάζει τη διεύθυνση του αντικειμένου Context ως πρόσθετη παράμετρο.
  • Χρησιμοποιώντας αυτήν τη διεύθυνση, εάν είναι απαραίτητο, οι μέθοδοι της κλάσης State μπορούν να αλλάξουν την "τρέχουσα κατάσταση" της κλάσης Context.

Χαρακτηριστικά του κρατικού προτύπου

  • Τα κρατικά αντικείμενα είναι συχνά μοναχικά.
  • Το Flyweight δείχνει πώς και πότε μπορούν να κοινοποιηθούν τα αντικείμενα State.
  • Το μοτίβο διερμηνέα μπορεί να χρησιμοποιήσει την κατάσταση για να ορίσει περιβάλλοντα κατά την ανάλυση.
  • Τα μοτίβα State και Bridge έχουν παρόμοιες δομές, εκτός από το ότι το Bridge επιτρέπει μια ιεραρχία κλάσεων φακέλου (αναλόγων κλάσεων "wrapper"), ενώ το State όχι. Αυτά τα μοτίβα έχουν παρόμοιες δομές αλλά εξυπηρετούν διαφορετικούς σκοπούς: Η κατάσταση επιτρέπει σε ένα αντικείμενο να αλλάξει τη συμπεριφορά του με βάση την εσωτερική του κατάσταση, ενώ το Bridge διαχωρίζει την αφαίρεση από την υλοποίησή της, ώστε να μπορούν να αλλάξουν ανεξάρτητα.
  • Η εφαρμογή του κρατικού προτύπου βασίζεται στο πρότυπο της στρατηγικής. Η διαφορά έγκειται στον σκοπό τους.

Εφαρμογή του κρατικού προτύπου

Εξετάστε ένα παράδειγμα μιας μηχανής κατάστασης με δύο πιθανές καταστάσεις και δύο συμβάντα.

#περιλαμβάνω χρησιμοποιώντας το namespace std? class Machine ( class State *current; public: Machine(); void setCurrent(State *s) (current = s; ) void on(); void off(); class State ( public: virtual void on (Machine *m) ( cout<< " already ON\n"; } virtual void off(Machine *m) { cout << " already OFF\n"; } }; void Machine::on() { current->για το θέμα αυτό); ) void Machine::off() (current->off(this); ) class ON: public State ( public: ON() ( cout<< " ON-ctor "; }; ~ON() { cout << " dtor-ON\n"; }; void off(Machine *m); }; class OFF: public State { public: OFF() { cout << " OFF-ctor "; }; ~OFF() { cout << " dtor-OFF\n"; }; void on(Machine *m) { cout << " going from OFF to ON"; m->setCurrent(new ON()); διαγράψτε αυτό? ) ); void ON::off(Machine *m) (cout<< " going from ON to OFF"; m->setCurrent(new OFF()); διαγράψτε αυτό? ) Machine::Machine() ( τρέχον = νέο OFF(); cout<< "\n"; } int main() { void(Machine:: *ptrs)() = { Machine::off, Machine::on }; Machine fsm; int num; while (1) { cout << "Enter 0/1: "; cin >>αριθμός; (fsm.*ptrs)(); ) )

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

Φαίνεται ότι όλα είναι σύμφωνα με το βιβλίο, αλλά υπάρχει μια απόχρωση. Πώς να εφαρμόσετε σωστά μεθόδους που δεν είναι σχετικές για μια δεδομένη κατάσταση; Για παράδειγμα, πώς μπορώ να αφαιρέσω ένα αντικείμενο από ένα άδειο καλάθι ή να πληρώσω για ένα άδειο καλάθι; Συνήθως, κάθε κλάση κατάστασης υλοποιεί μόνο τις σχετικές μεθόδους και διαφορετικά ρίχνει ένα InvalidOperationException .

Παραβίαση της αρχής της αντικατάστασης του Liskov για ένα άτομο. Ο Yaron Minsky πρότεινε μια εναλλακτική προσέγγιση: καθιστούν τα παράνομα κράτη μη αντιπροσωπεύσιμα. Αυτό καθιστά δυνατή τη μετακίνηση του ελέγχου σφαλμάτων από τον χρόνο εκτέλεσης στον χρόνο μεταγλώττισης. Ωστόσο, η ροή ελέγχου σε αυτή την περίπτωση θα οργανωθεί με βάση την αντιστοίχιση προτύπων και όχι τη χρήση πολυμορφισμού. Ευτυχώς,.

Μάθετε περισσότερα για το θέμα F# καθιστούν τα παράνομα κράτη μη αντιπροσωπεύσιμααποκαλύφθηκε στον ιστότοπο του Scott Vlashin.

Εξετάστε την εφαρμογή του "state" στο παράδειγμα ενός καλαθιού. Δεν υπάρχει ενσωματωμένος τύπος ένωσης στη C#. Διαχωρίστε δεδομένα και συμπεριφορά. Θα κωδικοποιήσουμε την ίδια την κατάσταση χρησιμοποιώντας το enum και τη συμπεριφορά ως ξεχωριστή κλάση. Για ευκολία, θα δηλώσουμε ένα χαρακτηριστικό που δεσμεύει το enum και την αντίστοιχη κλάση συμπεριφοράς, τη βασική κλάση «state» και θα προσθέσουμε μια μέθοδο επέκτασης για να περάσει από την enum στην κλάση συμπεριφοράς.

Υποδομή

δημόσια κλάση StateAttribute: Χαρακτηριστικό ( public Type StateType ( get; ) public StateAttribute(Type stateType) ( StateType = stateType ?? ρίχνω νέο ArgumentNullException(nameof(stateType)); ) ) δημόσια αφηρημένη τάξη κατάσταση όπου T: κλάση ( προστατευμένη κατάσταση(T οντότητα) ( Οντότητα = οντότητα ?? ρίχνω νέο ArgumentNullException(όνομα(οντότητα)); ) προστατευμένη οντότητα T ( get; ) ) δημόσια στατική κλάση StateCodeExtensions ( δημόσια στατική κατάσταση Να δηλώσω (αυτός ο κωδικός κατάστασης Enum, οντότητα αντικειμένου) όπου T: κλάση // ναι, ναι η ανάκλαση είναι αργή. Αντικαταστήστε με το δέντρο έκφρασης μεταγλώττισης // ή το IL Emit και θα είναι γρήγορο => (Κατάσταση ) Activator.CreateInstance(stateCode .GetType() .GetCustomAttribute ().StateType, οντότητα); )

Θεματική ενότητα

Ας δηλώσουμε την οντότητα "καλάθι":

Δημόσια διεπαφή IHasState όπου TEntity: κλάση ( TStateCode StateCode ( get; ) State State ( get; ) ) public partal class Καλάθι: IHasState ( δημόσιος χρήστης χρήστης ( get; προστατευμένο σύνολο; ) δημόσιο CartStateCode StateCode ( get; προστατευμένο σύνολο; ) δημόσια κατάσταση Κατάσταση => StateCode.ToState (Αυτό); δημόσιο δεκαδικό Σύνολο ( get; προστατευμένο σύνολο; ) προστατευμένη εικονική ICollection Προϊόντα ( get; set; ) = νέα λίστα () // Προστατευμένο μόνο ORM Cart() ( ) public Cart(User user) ( User = user ?? hedh νέο ArgumentNullException(nameof(user)); StateCode = StateCode = CartStateCode.Empty; ) public Cart(User user, IEnumerable Προϊόντα) : this(user) ( StateCode = StateCode = CartStateCode.Empty; foreach (var product in products) ( Products.Add(product); ) ) public Cart(User user, IEnumerable Προϊόντα, δεκαδικό σύνολο) : αυτό(χρήστης, προϊόντα) (αν (σύνολο<= 0) { throw new ArgumentException(nameof(total)); } Total = total; } }
Ας εφαρμόσουμε μία κλάση για κάθε κατάσταση καλαθιού: άδειο, ενεργό και πληρωμένο, αλλά δεν θα δηλώσουμε κοινή διεπαφή. Αφήστε κάθε κράτος να εφαρμόσει μόνο τη σχετική συμπεριφορά. Αυτό δεν σημαίνει ότι οι κλάσεις EmptyCartState , ActiveCartState και PaidCartState δεν μπορούν να υλοποιήσουν την ίδια διεπαφή. Μπορούν, αλλά μια τέτοια διεπαφή θα πρέπει να περιέχει μόνο τις διαθέσιμες μεθόδους σε κάθε κατάσταση. Στην περίπτωσή μας, η μέθοδος Προσθήκη είναι διαθέσιμη στο EmptyCartState και στο ActiveCartState, ώστε να μπορούμε να κληρονομήσουμε από το αφηρημένο AddableCartStateBase. Ωστόσο, μπορείτε να προσθέσετε προϊόντα μόνο σε ένα μη πληρωμένο καλάθι, επομένως δεν θα υπάρχει κοινή διεπαφή για όλες τις πολιτείες. Έτσι, εγγυόμαστε την απουσία InvalidOperationException στον κώδικά μας στο στάδιο της μεταγλώττισης.

Δημόσια μερική κλάση Καλάθι ( δημόσιος αριθμός CartStateCode: byte ( Empty, Active, Paid ) δημόσια διεπαφή IAddableCartState ( ActiveCartState Προσθήκη (προϊόν προϊόντος); IEnumerable Προϊόντα ( get; ) ) δημόσια διεπαφή INotEmptyCartState ( IEnumerable Προϊόντα ( get; ) δεκαδικό Σύνολο ( get; ) ) δημόσια αφηρημένη κλάση AddableCartState: State , IAddableCartState ( προστατευμένο AddableCartState(Οντότητα καλαθιού): βάση(οντότητα) ( ) δημόσια ActiveCartState Προσθήκη(προϊόν προϊόντος) ( Entity.Products.Add(product); δημόσιο IEαριθμήσιμο Προϊόντα => Entity.Products; ) δημόσια κλάση EmptyCartState: AddableCartState ( δημόσια EmptyCartState(Οντότητα καλαθιού): βάση(οντότητα) ( ) ) δημόσια κλάση ActiveCartState: AddableCartState, INotEmptyCartState (δημόσιο ActiveCartState(Δημόσια οντότητα Καλαθιού): Βασική οντότητα(συνολική οντότητα) Entity.Total = σύνολο;Entity.StateCode = CartStateCode.Paid;return (PaidCartState)Entity.State; ) δημόσιο κράτος Remove(Product product) ( Entity.Products.Remove(product); if(!Entity.Products.Any()) ( Entity.StateCode = CartStateCode.Empty; ) return Entity.State; ) public EmptyCartState Clear() ( Entity. Products.Clear(); Entity.StateCode = CartStateCode.Empty; επιστροφή (EmptyCartState)Entity.State; ) δημόσιο δεκαδικό Σύνολο => Products.Sum(x => x.Price); ) δημόσια κλάση PaidCartState: Πολιτεία , INotEmptyCartState ( δημόσιο IEnumerable Προϊόντα => Entity.Products; δημόσιο δεκαδικό Σύνολο => Οντότητα.Σύνολο; δημόσιο PaidCartState(Οντότητα καλαθιού): βάση(οντότητα) ( ) ) )
Οι πολιτείες δηλώνονται ένθετες ( φωλιασμένος) τα μαθήματα δεν είναι τυχαία. Οι ένθετες κλάσεις έχουν πρόσβαση στα προστατευμένα μέλη της κλάσης Cart, πράγμα που σημαίνει ότι δεν χρειάζεται να θυσιάσουμε την ενθυλάκωση οντοτήτων για να εφαρμόσουμε συμπεριφορά. Για να μην γεμίσει το αρχείο κλάσης οντοτήτων, χώρισα τη δήλωση σε δύο: Cart.cs και CartStates.cs χρησιμοποιώντας λέξη-κλειδίμερικός.

Δημόσια δράσηΑποτέλεσμα GetViewResult(Κατάσταση cartState) ( switch (cartState) ( case Cart.ActiveCartState activeState: return View("Active", activeState); case Cart.EmptyCartState κενόState: επιστροφή Προβολή("Empty", whiteState); case Cart.PaidCartState paidCartState: επιστροφή Προβολή(" Paid", paidCartState); προεπιλογή: δημιουργία νέου InvalidOperationException(); ) )
Ανάλογα με την κατάσταση του καλαθιού, θα χρησιμοποιήσουμε διαφορετικές προβολές. Για ένα άδειο καλάθι, θα εμφανίσουμε το μήνυμα "Το καλάθι σας είναι άδειο". Το ενεργό καλάθι θα περιέχει μια λίστα προϊόντων, τη δυνατότητα αλλαγής του αριθμού των προϊόντων και αφαίρεσης ορισμένων από αυτά, το κουμπί «checkout» και το συνολικό ποσό της αγοράς.

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

συμπέρασμα

Στον κώδικα εφαρμογής, μπορούμε να εργαστούμε στις αναφορές διεπαφής IAddableCartState και INotEmptyCartState για να επαναχρησιμοποιήσουμε τον κώδικα που είναι υπεύθυνος για την προσθήκη αντικειμένων στο καλάθι και την εμφάνιση των αντικειμένων στο καλάθι. Νομίζω ότι η αντιστοίχιση προτύπων είναι κατάλληλη για τη ροή ελέγχου στη C# μόνο όταν δεν υπάρχει τίποτα κοινό μεταξύ των τύπων. Σε άλλες περιπτώσεις, η εργασία στον σύνδεσμο βάσης είναι πιο βολική. Μια παρόμοια τεχνική μπορεί να εφαρμοστεί όχι μόνο για την κωδικοποίηση της συμπεριφοράς μιας οντότητας, αλλά και για .

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

Το μοτίβο "State" περιλαμβάνει την κατανομή μιας βασικής κλάσης ή διεπαφής για όλες τις έγκυρες λειτουργίες και ενός κληρονόμου για κάθε πιθανή κατάσταση

Πότε να χρησιμοποιήσετε το μοτίβο κατάστασης

    Όταν η συμπεριφορά ενός αντικειμένου πρέπει να εξαρτάται από την κατάστασή του και μπορεί να αλλάξει δυναμικά κατά το χρόνο εκτέλεσης

    Όταν χρησιμοποιούνται πολλαπλές δομές υπό όρους στον κώδικα των μεθόδων αντικειμένου, η επιλογή των οποίων εξαρτάται από την τρέχουσα κατάσταση του αντικειμένου

Διάγραμμα UML του μοτίβου "Κατάσταση":

Εφαρμογή του μοτίβου κατάστασης στο C#

χρησιμοποιώντας το σύστημα. χώρος ονομάτων DoFactory.GangOfFour.State.Structural( /// /// Κλάση εκκίνησης MainApp για Δομικό /// Κατάσταση Σχεδιασμού Μοτίβο. /// class MainApp( /// /// Σημείο εισόδου στην εφαρμογή της κονσόλας. /// static void Main() ( // Ρύθμιση περιβάλλοντος σε κατάσταση Context c = new Context(new ConcreteStateA()); // Issue requests, που εναλλάσσει την κατάσταση c.Request(); c.Request(); c.Request() ;c.Request(); // Περιμένετε για χρήστη Console.ReadKey(); ) ) /// /// Η αφηρημένη τάξη "Πολιτεία" ///αφηρημένη τάξη Κατάσταση ( δημόσιο αφηρημένο κενό Handle(Context context); ) /// κλάση ConcreteStateA: Κατάσταση ( δημόσια παράκαμψη void Handle(Context context) (context.State = new ConcreteStateB(); ) ) /// /// Κατηγορία "ConcreteState" ///κλάση ConcreteStateB: Κατάσταση ( δημόσια παράκαμψη void Handle(Context context) (context.State = new ConcreteStateA(); ) ) /// /// Η κλάση "Context" /// class Context ( private State _state; // Constructor public Context(State state) ( this.State = state; ) // Λαμβάνει ή ορίζει το κράτος δημόσιο State State ( get ( return _state; ) set ( _state = value; Console.WriteLine ("Κατάσταση: " + _state.GetType().Όνομα); ) ) δημόσιο κενό αίτημα() ( _state.Handle(this); ) ) )

Ένα παράδειγμα του κρατικού προτύπου από την πραγματική ζωή

Παραδείγματα στο .NET Framework

  • Εφαρμόζει το CommunicationObject κρατική μηχανήμετάβαση μεταξύ καταστάσεων πελάτη WCF: Δημιουργήθηκε, Άνοιγμα, Άνοιγμα, Κλείσιμο, Κλειστό και Σφάλμα.
  • Το Task υλοποιεί μια μηχανή κατάστασης για μετάβαση μεταξύ των καταστάσεων εργασιών: Δημιουργήθηκε, WaitingForActivation, WaitingToRun, Running, Run ToCompletion, Canceled, Faulted.