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

Πάρα πολλές παράμετροι σε μεθόδους Java, Μέρος 3: Μοτίβο δημιουργού

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

Στη δεύτερη έκδοση του Effective Java, ο Josh Bloch παρουσιάζει τη χρήση του μοτίβου builder στο στοιχείο # 2 για την αντιμετώπιση κατασκευαστών που απαιτούν πάρα πολλές παραμέτρους. Το Bloch όχι μόνο επιδεικνύει τον τρόπο χρήσης του Builder, αλλά εξηγεί τα πλεονεκτήματά του σε σχέση με τους κατασκευαστές που δέχονται μεγάλο αριθμό παραμέτρων. Θα φτάσω σε αυτά τα πλεονεκτήματα στο τέλος αυτής της ανάρτησης, αλλά πιστεύω ότι είναι σημαντικό να επισημάνω ότι ο Bloch έχει αφιερώσει ένα ολόκληρο στοιχείο στο βιβλίο του σε αυτήν την πρακτική.

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

Person.java (χωρίς μοτίβο οικοδόμου)

πακέτο dustin.example; / ** * Η κατηγορία ατόμων χρησιμοποιείται ως μέρος της επίδειξης πάρα πολλών παραμέτρων * * @author Dustin * / Πρόσωπο δημόσιας τάξης {private final String lastName; ιδιωτικό τελικό String firstName; ιδιωτικό τελικό String middleName; ιδιωτικός τελικός χαιρετισμός String; ιδιωτικό τελικό επίθημα συμβολοσειράς; ιδιωτικό τελικό String streetAddress; ιδιωτική τελική πόλη String; ιδιωτική τελική κατάσταση String; ιδιωτικό τελικό boolean isFemale; ιδιωτικό τελικό boolean is Employed; ιδιωτικό τελικό boolean isHomewOwner; public Person (final String newLastName, final String newFirstName, final String newMiddleName, final String newSalutation, final String newSuffix, final String newStreetAddress, final String newCity, final String newState, final boolean newIsFemale, final boolean newIsEm Employed, final booles lastName = newLastName; this.firstName = newFirstName; this.middleName = newMiddleName; this.salutation = newSalutation; this.suffix = newSuffix; this.streetAddress = newStreetAddress; this.city = newCity; this.state = newState; this.isFemale = newIsFemale; this.isEmableded = newIsEmableded; this.isHomewOwner = newIsHomeOwner; }} 

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

PersonBuilder.java

πακέτο dustin.example; δημόσια τάξη PersonBuilder {private String newLastName; ιδιωτική συμβολοσειρά newFirstName; ιδιωτικό String newMiddleName; private String newSalutation; ιδιωτικό String newSuffix; ιδιωτικό String newStreetAddress; ιδιωτικό String newCity; ιδιωτικό String newState; ιδιωτικό boolean newIsFemale; ιδιωτικό boolean newIsEm Employed; ιδιωτικό boolean newIsHomeOwner; δημόσιο PersonBuilder () {} δημόσιο PersonBuilder setNewLastName (String newLastName) {this.newLastName = newLastName; επιστρέψτε αυτό. } public PersonBuilder setNewFirstName (String newFirstName) {this.newFirstName = newFirstName; επιστρέψτε αυτό. } public PersonBuilder setNewMiddleName (συμβολοσειρά newMiddleName) {this.newMiddleName = newMiddleName; επιστρέψτε αυτό. } public PersonBuilder setNewSalutation (String newSalutation) {this.newSalutation = newSalutation; επιστρέψτε αυτό. } public PersonBuilder setNewSuffix (συμβολοσειρά newSuffix) {this.newSuffix = newSuffix; επιστρέψτε αυτό. } public PersonBuilder setNewStreetAddress (String newStreetAddress) {this.newStreetAddress = newStreetAddress; επιστρέψτε αυτό. } δημόσιο PersonBuilder setNewCity (String newCity) {this.newCity = newCity; επιστρέψτε αυτό. } δημόσιο PersonBuilder setNewState (String newState) {this.newState = newState; επιστρέψτε αυτό. } public PersonBuilder setNewIsFemale (boolean newIsFemale) {this.newIsFemale = newIsFemale; επιστρέψτε αυτό. } public PersonBuilder setNewIsEmableded (boolean newIsEm Employed) {this.newIsEmableded = newIsEmableded; επιστρέψτε αυτό. } public PersonBuilder setNewIsHomeOwner (boolean newIsHomeOwner) {this.newIsHomeOwner = newIsHomeOwner; επιστρέψτε αυτό. } public Person createPerson () {return new Person (newLastName, newFirstName, newMiddleName, newSalutation, newSuffix, newStreetAddress, newCity, newState, newIsFemale, newIsEmableded, newIsHomeOwner); }} 

Προτιμώ να έχω το Builder μου ως ένθετη τάξη μέσα στην τάξη του οποίου το αντικείμενο δημιουργεί, αλλά η αυτόματη δημιουργία ενός αυτόνομου Builder του NetBeans είναι πολύ εύκολο στη χρήση. Μια άλλη διαφορά μεταξύ του Builder που δημιουργείται από το NetBeans και του Builders που θέλω να γράψω είναι ότι οι προτιμώμενες εφαρμογές Builder μου απαιτούσαν πεδία που παρέχονται στον κατασκευαστή του Builder αντί να παρέχουν έναν κατασκευαστή χωρίς ορίσματα. Η επόμενη λίστα κωδικών δείχνει το my Πρόσωπο τάξη από πάνω με ένα Builder που προστέθηκε σε αυτήν ως ένθετη τάξη.

Person.java με Nested Person.Builder

πακέτο dustin.example; / ** * Η κατηγορία ατόμων χρησιμοποιείται ως μέρος της επίδειξης πάρα πολλών παραμέτρων * * @author Dustin * / Πρόσωπο δημόσιας τάξης {private final String lastName; ιδιωτικό τελικό String firstName; ιδιωτικό τελικό String middleName; ιδιωτικός τελικός χαιρετισμός String; ιδιωτικό τελικό επίθημα συμβολοσειράς; ιδιωτικό τελικό String streetAddress; ιδιωτική τελική πόλη String; ιδιωτική τελική κατάσταση String; ιδιωτικό τελικό boolean isFemale; ιδιωτικό τελικό boolean is Employed; ιδιωτικό τελικό boolean isHomewOwner; public Person (final String newLastName, final String newFirstName, final String newMiddleName, final String newSalutation, final String newSuffix, final String newStreetAddress, final String newCity, final String newState, final boolean newIsFemale, final boolean newIsEm Employed, final booles lastName = newLastName; this.firstName = newFirstName; this.middleName = newMiddleName; this.salutation = newSalutation; this.suffix = newSuffix; this.streetAddress = newStreetAddress; this.city = newCity; this.state = newState; this.isFemale = newIsFemale; this.isEmableded = newIsEmableded; this.isHomewOwner = newIsHomeOwner; } δημόσια στατική τάξη PersonBuilder {private String nestedLastName; ιδιωτικό String nestedFirstName; ιδιωτικό String nestedMiddleName; ιδιωτικό String nestedSalutation; ιδιωτικό String nestedSuffix; ιδιωτικό String nestedStreetAddress; ιδιωτικό String nestedCity; ιδιωτικό String nestedState; ιδιωτικό boolean nestedIsFemale; ιδιωτικό boolean nestedIsEm Employed; ιδιωτικό boolean nestedIsHomeOwner; δημόσιο PersonBuilder (final String newFirstName, final String newCity, final String newState) {this.nestedFirstName = newFirstName; this.nestedCity = newCity; this.nestedState = newState; } public PersonBuilder lastName (συμβολοσειρά newLastName) {this.nestedLastName = newLastName; επιστρέψτε αυτό. } δημόσιο PersonBuilder firstName (συμβολοσειρά newFirstName) {this.nestedFirstName = newFirstName; επιστρέψτε αυτό. } δημόσιο PersonBuilder middleName (String newMiddleName) {this.nestedMiddleName = newMiddleName; επιστρέψτε αυτό. } δημόσιος χαιρετισμός PersonBuilder (String newSalutation) {this.nestedSalutation = newSalutation; επιστρέψτε αυτό. } δημόσιο επίθημα PersonBuilder (String newSuffix) {this.nestedSuffix = newSuffix; επιστρέψτε αυτό. } δημόσιο PersonBuilder streetAddress (String newStreetAddress) {this.nestedStreetAddress = newStreetAddress; επιστρέψτε αυτό. } δημόσια πόλη PersonBuilder (String newCity) {this.nestedCity = newCity; επιστρέψτε αυτό. } δημόσια κατάσταση PersonBuilder (String newState) {this.nestedState = newState; επιστρέψτε αυτό. } Public PersonBuilder isFemale (boolean newIsFemale) {this.nestedIsFemale = newIsFemale; επιστρέψτε αυτό. } public PersonBuilder isEmableded (boolean newIsEmableded) {this.nestedIsEmemployed = newIsEmableded; επιστρέψτε αυτό. } Public PersonBuilder isHomeOwner (boolean newIsHomeOwner) {this.nestedIsHomeOwner = newIsHomeOwner; επιστρέψτε αυτό. } public Person createPerson () {return new Person (nestedLastName, nestedFirstName, nestedMiddleName, nestedSalutation, nestedSuffix, nestedStreetAddress, nestedCity, nestedState, nestedIsFemale, nestedIsEmableded, nestedIsHomeOwner); }}} 

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

Person.java με ένθετο Builder, προσαρμοσμένους τύπους και αντικείμενο παραμέτρων

πακέτο dustin.example; / ** * Η κατηγορία ατόμων χρησιμοποιείται ως μέρος της επίδειξης πάρα πολλών παραμέτρων * * @author Dustin * / Πρόσωπο δημόσιας τάξης {ιδιωτικό τελικό όνομα πλήρους ονόματος; ιδιωτική τελική διεύθυνση Διεύθυνση; ιδιωτικό τελικό φύλο ιδιωτικό τελικό EmploymentStatus απασχόληση? ιδιωτικό τελικό HomeownerStatus homeOwnerStatus; / ** * Ο παραμετροποιημένος κατασκευαστής μπορεί να είναι ιδιωτικός, επειδή μόνο ο εσωτερικός μου κατασκευαστής * πρέπει να με καλέσει για να παρέχει μια παρουσία στους πελάτες. * * @param newName Όνομα αυτού του ατόμου. * @param newAddress Διεύθυνση αυτού του ατόμου. * @param newGender Φύλο αυτού του ατόμου. * @param newEm Employment Απασχόληση κατάσταση αυτού του ατόμου. * Κατάσταση ιδιοκτησίας @param newHomeOwner Home αυτού του ατόμου. * / ιδιωτικό άτομο (τελικό πλήρες όνομα νέο όνομα, τελική διεύθυνση νέα διεύθυνση, τελικό φύλο νέο φύλο, τελικό EmploymentStatus newEm Employment, final HomeownerStatus newHomeOwner) {this.name = newName; this.address = newAddress; this.gender = newGender; this.employment = newEm Employment; this.homeOwnerStatus = newHomeOwner; } δημόσιο Πλήρες όνομα getName () {return this.name; } δημόσια διεύθυνση getAddress () {return this.address; } δημόσιο Gender getGender () {return this.gender; } δημόσιο EmploymentStatus getEm Employment () {return this.employment; } δημόσιο HomeownerStatus getHomeOwnerStatus () {επιστροφή αυτού.homeOwnerStatus; } / ** * Κατηγορία Builder όπως περιγράφεται στη δεύτερη έκδοση του Joshua Bloch's * Αποτελεσματική Java που χρησιμοποιείται για τη δημιουργία μιας παρουσίας {@link Person}. * / δημόσια στατική τάξη PersonBuilder {private FullName nestedName; ιδιωτική διεύθυνση nestedAddress; ιδιωτικό φύλο nestedGender; ιδιωτικό EmploymentStatus nestedEmemploymentStatus; ιδιωτικό HomeownerStatus nestedHomeOwnerStatus; δημόσιο PersonBuilder (τελικό πλήρες όνομα newFullName, τελική διεύθυνση newAddress) {this.nestedName = newFullName; this.nestedAddress = newAddress; } δημόσιο όνομα PersonBuilder (τελικό πλήρες όνομα νέο όνομα) {this.nestedName = newName; επιστρέψτε αυτό. } δημόσια διεύθυνση PersonBuilder (τελική διεύθυνση newAddress) {this.nestedAddress = newAddress; επιστρέψτε αυτό. } δημόσιο φύλο PersonBuilder (final Gender newGender) {this.nestedGender = newGender; επιστρέψτε αυτό. } δημόσια απασχόληση PersonBuilder (τελικό EmploymentStatus newEmemploymentStatus) {this.nestedEmemploymentStatus = newEmemploymentStatus; επιστρέψτε αυτό. } δημόσιο PersonBuilder homeOwner (τελικό HomeownerStatus newHomeOwnerStatus) {this.nestedHomeOwnerStatus = newHomeOwnerStatus; επιστρέψτε αυτό. } public Person createPerson () {return new Person (nestedName, nestedAddress, nestedGender, nestedEmemploymentStatus, nestedHomeOwnerStatus); }}} 

Το τελευταίο ζευγάρι καταχωρίσεων κώδικα δείχνει πώς χρησιμοποιείται συνήθως ένα Builder - για την κατασκευή ενός αντικειμένου. Πράγματι, το αντικείμενο στο εργαλείο δημιουργίας (στοιχείο # 2) στη δεύτερη έκδοση του Joshua Bloch του Effective Java βρίσκεται στο κεφάλαιο για τη δημιουργία (και καταστροφή) αντικειμένου. Ωστόσο, το πρόγραμμα δημιουργίας μπορεί να βοηθήσει έμμεσα με μεθόδους μη κατασκευαστή επιτρέποντας έναν ευκολότερο τρόπο κατασκευής παραμέτρων αντικειμένων που μεταβιβάζονται σε μεθόδους.