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

Μια ματιά στο σχέδιο σύνθετου σχεδιασμού

Τις προάλλες άκουγα το Εθνικό Δημόσιο Ραδιόφωνο Συζήτηση αυτοκινήτου, μια δημοφιλή εβδομαδιαία μετάδοση κατά την οποία οι καλούντες κάνουν ερωτήσεις σχετικά με τα οχήματά τους. Πριν από κάθε διακοπή του προγράμματος, οι οικοδεσπότες της εκπομπής ζητούν από τους καλούντες να καλέσουν το 1-800-CAR-TALK, το οποίο αντιστοιχεί στο 1-800-227-8255. Φυσικά, το πρώτο αποδεικνύεται πολύ πιο εύκολο να θυμόμαστε από το δεύτερο, εν μέρει επειδή οι λέξεις "CAR TALK" είναι σύνθετες: δύο λέξεις που αντιπροσωπεύουν επτά ψηφία. Οι άνθρωποι βρίσκουν γενικά ευκολότερο να ασχοληθούν με τα σύνθετα, παρά τα μεμονωμένα συστατικά τους. Ομοίως, κατά την ανάπτυξη αντικειμενοστραφούς λογισμικού, είναι συχνά βολικό να χειρίζεστε σύνθετα όπως ακριβώς χειρίζεστε μεμονωμένα στοιχεία. Αυτή η υπόθεση αντιπροσωπεύει τη θεμελιώδη αρχή του σχεδίου σύνθετου σχεδιασμού, το θέμα αυτού Μοτίβα σχεδίασης Java δόση πληρωμής.

Το σύνθετο μοτίβο

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

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

Σε Σχεδιαστικά πρότυπα, οι συγγραφείς περιγράφουν το σύνθετο μοτίβο ως εξής:

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

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

Στο διάγραμμα τάξης του σχήματος 1, χρησιμοποίησα ονόματα τάξεων από Σχέδιο σχεδίουΣυζήτηση σύνθετων προτύπων: Συστατικό αντιπροσωπεύει μια βασική κλάση (ή πιθανώς μια διεπαφή) για πρωτόγονα αντικείμενα και Σύνθετος αντιπροσωπεύει μια σύνθετη τάξη. Για παράδειγμα, το Συστατικό κλάση μπορεί να αντιπροσωπεύει μια βασική τάξη για πρωτόγονες γραφικών, ενώ το Σύνθετος τάξη μπορεί να αντιπροσωπεύει ένα Σχέδιο τάξη. Σχήμα 1 Φύλλο κλάση αντιπροσωπεύει ένα συγκεκριμένο πρωτόγονο αντικείμενο? για παράδειγμα, α Γραμμή τάξη ή α Κείμενο τάξη. ο Λειτουργία1 () και Λειτουργία2 () οι μέθοδοι αντιπροσωπεύουν συγκεκριμένες μεθόδους τομέα που εφαρμόζονται και από τα δύο Συστατικό και Σύνθετος τάξεις.

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

// Αυτή η μέθοδος είναι μια σύνθετη μέθοδος δημόσιας άκυρης κλήρωσης () {// Επανάληψη των στοιχείων για το (int i = 0; i <getComponentCount (); ++ i) {// Λάβετε μια αναφορά στο στοιχείο και επικαλέστε την κλήρωση του Μέθοδος Συστατικό στοιχείο = getComponent (i); component.draw (); }} 

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

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

// Αυτή η μέθοδος εφαρμόζεται σε μια κλάση που δεν σχετίζεται με το // Component and Composite class public void repaint (Component komponen) {// Το στοιχείο μπορεί να είναι σύνθετο, αλλά δεδομένου ότι επεκτείνει // την Component class, αυτή η μέθοδος δεν χρειάζεται // διάκριση μεταξύ συστατικών και σύνθετων στοιχείων.draw (); } 

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

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

... if (component.isComposite ()) {Composite composite = (Composite) στοιχείο; composite.addComponent (someComponentThatCouldBeAComposite); } ... 

Παρατηρήστε ότι το addComponent () η μέθοδος περνά a Συστατικό αναφορά, η οποία μπορεί να είναι είτε ένα πρωτόγονο συστατικό είτε ένα σύνθετο. Επειδή αυτό το στοιχείο μπορεί να είναι σύνθετο, μπορείτε να συνθέσετε στοιχεία σε μια δομή δέντρου, όπως υποδεικνύεται από το προαναφερθέν απόσπασμα από Σχεδιαστικά πρότυπα.

Το σχήμα 2 δείχνει μια εναλλακτική εφαρμογή σύνθετων προτύπων.

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

... component.addComponent (someComponentThatCouldBeAComposite); ... 

Αλλά, εάν το Συστατικό Η αναφορά στο προηγούμενο τμήμα κώδικα δεν αναφέρεται σε α Σύνθετος, τι πρέπει addComponent () κάνω? Αυτό είναι ένα σημαντικό σημείο διαφωνίας με την υλοποίηση σύνθετων προτύπων του Σχήματος 2. Επειδή τα πρωτόγονα συστατικά δεν περιέχουν άλλα συστατικά, η προσθήκη ενός συστατικού σε ένα άλλο συστατικό δεν έχει νόημα, έτσι το Component.addComponent () μέθοδος μπορεί είτε να αποτύχει σιωπηλά είτε να ρίξει μια εξαίρεση. Συνήθως, η προσθήκη ενός στοιχείου σε ένα άλλο πρωτόγονο στοιχείο θεωρείται σφάλμα, επομένως η εξαίρεση είναι ίσως η καλύτερη πορεία δράσης.

Λοιπόν, ποια εφαρμογή σύνθετων προτύπων - αυτή στο Σχήμα 1 ή αυτή στο Σχήμα 2 - λειτουργεί καλύτερα; Αυτό είναι πάντα ένα θέμα μεγάλης συζήτησης μεταξύ των εφαρμοστών σύνθετων προτύπων. Σχεδιαστικά πρότυπα προτιμά την εφαρμογή του Σχήματος 2 επειδή δεν χρειάζεται ποτέ να κάνετε διάκριση μεταξύ εξαρτημάτων και κοντέινερ και ποτέ δεν χρειάζεται να εκτελέσετε ένα cast. Προσωπικά, προτιμώ την υλοποίηση του Σχήματος 1, επειδή έχω μεγάλη αντίθεση με τις μεθόδους εφαρμογής σε μια τάξη που δεν έχουν νόημα για αυτόν τον τύπο αντικειμένου.

Τώρα που κατανοείτε το σύνθετο μοτίβο και πώς μπορείτε να το εφαρμόσετε, ας εξετάσουμε ένα παράδειγμα σύνθετου μοτίβου με το πλαίσιο Apache Struts JavaServer Pages (JSP).

Το σύνθετο σχέδιο και τα πλακίδια Struts

Το πλαίσιο Apache Struts περιλαμβάνει μια βιβλιοθήκη ετικετών JSP, γνωστή ως Tiles, που σας επιτρέπει να συνθέσετε μια ιστοσελίδα από πολλά JSP. Το Tiles είναι στην πραγματικότητα μια υλοποίηση του μοτίβου CompositeView J2EE (Java 2 Platform, Enterprise Edition), το οποίο βασίζεται στο Σχεδιαστικά πρότυπα Σύνθετο μοτίβο. Πριν συζητήσουμε τη συνάφεια του μοτίβου σύνθετων με τη βιβλιοθήκη ετικετών πλακιδίων, ας εξετάσουμε πρώτα τη λογική για τα πλακίδια και τον τρόπο που το χρησιμοποιείτε. Εάν είστε ήδη εξοικειωμένοι με τα Struts Tiles, μπορείτε να διαβάσετε τις παρακάτω ενότητες και να ξεκινήσετε την ανάγνωση στο "Use the Composite Pattern with Struts Tiles."

Σημείωση: Μπορείτε να διαβάσετε περισσότερα σχετικά με το μοτίβο J2EE CompositeView στο "Web Application Components Made Easy with Composite View" (JavaWorld, Δεκέμβριος 2001) άρθρο.

Οι σχεδιαστές συχνά κατασκευάζουν ιστοσελίδες με ένα σύνολο διακριτών περιοχών. Για παράδειγμα, η Ιστοσελίδα του Σχήματος 3 περιλαμβάνει πλευρική γραμμή, κεφαλίδα, περιοχή περιεχομένου και υποσέλιδο.

Οι ιστότοποι συχνά περιλαμβάνουν πολλές ιστοσελίδες με πανομοιότυπες διατάξεις, όπως η διάταξη πλευρικής γραμμής / κεφαλίδας / περιεχομένου / υποσέλιδου του σχήματος 3. Το Struts Tiles σάς επιτρέπει να επαναχρησιμοποιείτε περιεχόμενο και διάταξη σε πολλές ιστοσελίδες. Πριν συζητήσουμε αυτήν την επαναχρησιμοποίηση, ας δούμε πώς η διάταξη του σχήματος 3 εφαρμόζεται παραδοσιακά μόνο με HTML.

Εφαρμόστε σύνθετες διατάξεις με το χέρι

Το παράδειγμα 1 δείχνει πώς μπορείτε να εφαρμόσετε την ιστοσελίδα του σχήματος 3 με HTML:

Παράδειγμα 1. Μια σύνθετη διάταξη που εφαρμόζεται με το χέρι

    Εφαρμογή σύνθετων διατάξεων με το χέρι <% - Ένας πίνακας παρουσιάζει όλο το περιεχόμενο αυτής της σελίδας -%>
Συνδέσεις

Σπίτι

Προϊόντα

Λήψεις

άσπρα χαρτιά

Επικοινωνήστε μαζί μας

Καλώς ήλθατε στην Sabreware, Inc.
Περιεχόμενο για συγκεκριμένη σελίδα πηγαίνει εδώ

Ευχαριστώ που περάσατε!

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

Εφαρμόστε σύνθετες διατάξεις με JSP περιλαμβάνει

Το παράδειγμα 2 δείχνει μια εφαρμογή της ιστοσελίδας του σχήματος 3 που χρησιμοποιεί :