Programovanie

Príliš veľa parametrov v metódach Java, časť 3: Vzor staviteľa

Vo svojich dvoch bezprostredne predchádzajúcich príspevkoch som sa pozrel na zníženie počtu parametrov potrebných na vyvolanie konštruktora alebo metódy pomocou vlastných typov a objektov parametrov. V tomto príspevku sa pozriem na použitie vzoru staviteľa na zníženie počtu parametrov potrebných pre konštruktéra s určitou diskusiou o tom, ako môže tento vzor dokonca pomôcť pri metódach bez konštruktora, ktoré berú príliš veľa parametrov.

V druhom vydaní efektívnej Javy uvádza Josh Bloch použitie vzoru staviteľa v položke č. 2 na prácu s konštruktormi, ktoré vyžadujú príliš veľa parametrov. Bloch nielen demonštruje, ako používať Builder, ale vysvetľuje aj jeho výhody oproti konštruktérom akceptujúcim veľké množstvo parametrov. K týmto výhodám sa dostanem na konci tohto príspevku, ale myslím si, že je dôležité zdôrazniť, že Bloch tejto praxi venoval celú položku vo svojej knihe.

Na ilustráciu výhod tohto prístupu uvediem nasledujúci príklad Osoba trieda. Nemá všetky metódy, ktoré by som do takejto triedy zvyčajne pridal, pretože sa chcem zamerať na jej konštrukciu.

Person.java (bez vzoru staviteľa)

balenie zásypu.príklady; / ** * Trieda osôb použitá ako súčasť demonštrácie príliš veľa parametrov. * * @author Dustin * / verejná trieda Osoba {private final String priezvisko; súkromné ​​konečné reťazec meno; private final String middleName; súkromné ​​záverečné pozdravenie reťazca; súkromná koncová prípona Reťazec; súkromná konečná reťazec streetAddress; súkromné ​​konečné mesto String; súkromný konečný stav reťazca; private final boolean isFemale; súkromný konečný boolean jezamestnaný; private final 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 newIsEmployed, final boolean newIs priezvisko = 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.isEmployed = newIsEmployed; this.isHomewOwner = newIsHomeOwner; }} 

Konštruktor tejto triedy funguje, ale kód klienta je ťažké správne používať. Na uľahčenie používania konštruktora je možné použiť vzor Builder. Ako som už písal, NetBeans to za mňa refaktoruje. Ďalej je uvedený príklad rekonfigurovaného kódu (NetBeans to robí vytvorením všetkých nových tried Builder).

PersonBuilder.java

balenie zásypu.príklady; verejná trieda PersonBuilder {private String newLastName; private String newFirstName; private String newMiddleName; private String newSalutation; private String newSuffix; private String newStreetAddress; private String newCity; súkromný reťazec newState; private boolean newIsFemale; private boolean newIsEmployed; súkromný booleovský newIsHomeOwner; public PersonBuilder () {} public PersonBuilder setNewLastName (reťazec newLastName) {this.newLastName = newLastName; vráťte to; } public PersonBuilder setNewFirstName (reťazec newFirstName) {this.newFirstName = newFirstName; vráťte to; } public PersonBuilder setNewMiddleName (reťazec newMiddleName) {this.newMiddleName = newMiddleName; vráťte to; } public PersonBuilder setNewSalutation (reťazec newSalutation) {this.newSalutation = newSalutation; vráťte to; } public PersonBuilder setNewSuffix (reťazec newSuffix) {this.newSuffix = newSuffix; vráťte to; } public PersonBuilder setNewStreetAddress (reťazec newStreetAddress) {this.newStreetAddress = newStreetAddress; vráťte to; } public PersonBuilder setNewCity (String newCity) {this.newCity = newCity; vráťte to; } public PersonBuilder setNewState (String newState) {this.newState = newState; vráťte to; } public PersonBuilder setNewIsFemale (boolean newIsFemale) {this.newIsFemale = newIsFemale; vráťte to; } public PersonBuilder setNewIsEmployed (boolean newIsEmployed) {this.newIsEmployed = newIsEmployed; vráťte to; } public PersonBuilder setNewIsHomeOwner (boolean newIsHomeOwner) {this.newIsHomeOwner = newIsHomeOwner; vráťte to; } public Person createPerson () {return new Person (newLastName, newFirstName, newMiddleName, newSalutation, newSuffix, newStreetAddress, newCity, newState, newIsFemale, newIsEmployed, newIsHomeOwner); }} 

Najradšej mám svoj Builder ako vnorenú triedu vo vnútri triedy, ktorej objekt vytvára, ale automatické generovanie samostatného Buildera NetBeans je veľmi jednoduché. Ďalším rozdielom medzi NetBeans generovaným Builderom a Buildermi, ktoré rád píšem, je to, že moje preferované implementácie Builderu majú skôr požadované polia poskytnuté v konštruktore Buildera, než aby poskytovali konštruktor bez argumentov. Nasledujúci zoznam kódov zobrazuje moje Osoba triedy zhora a do nej pridaný Builder ako vnorená trieda.

Person.java s vnorenou osobou. Staviteľ

balenie zásypu.príklady; / ** * Trieda osôb použitá ako súčasť ukážky príliš veľa parametrov. * * @author Dustin * / verejná trieda Osoba {private final String priezvisko; súkromné ​​konečné reťazec meno; private final String middleName; súkromné ​​záverečné pozdravenie reťazca; súkromná koncová prípona Reťazec; súkromná konečná reťazec streetAddress; súkromné ​​konečné mesto String; súkromný konečný stav reťazca; private final boolean isFemale; súkromný konečný boolean jezamestnaný; súkromný posledný boolean jeHomewOwner; 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 newIsEmployed, final boolean newIs priezvisko = 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.isEmployed = newIsEmployed; this.isHomewOwner = newIsHomeOwner; } verejná statická trieda PersonBuilder {súkromný reťazec nestedLastName; private String nestedFirstName; private String nestedMiddleName; private String nestedSalutation; private String nestedSuffix; private String nestedStreetAddress; private String nestedCity; private String nestedState; private boolean nestedIsFemale; private boolean nestedIsEmployed; private boolean nestedIsHomeOwner; public PersonBuilder (konečný reťazec newFirstName, konečný reťazec newCity, konečný reťazec newState) {this.nestedFirstName = newFirstName; this.nestedCity = newCity; this.nestedState = newState; } verejné PersonBuilder priezvisko (reťazec newLastName) {this.nestedLastName = newLastName; vráťte to; } public PersonBuilder firstName (reťazec newFirstName) {this.nestedFirstName = newFirstName; vráťte to; } public PersonBuilder middleName (reťazec newMiddleName) {this.nestedMiddleName = newMiddleName; vráťte to; } verejné oslovenie PersonBuilder (reťazec newSalutation) {this.nestedSalutation = newSalutation; vráťte to; } verejná prípona PersonBuilder (reťazec newSuffix) {this.nestedSuffix = newSuffix; vráťte to; } public PersonBuilder streetAddress (reťazec newStreetAddress) {this.nestedStreetAddress = newStreetAddress; vráťte to; } verejné mesto PersonBuilder (reťazec newCity) {this.nestedCity = newCity; vráťte to; } public State PersonBuilder state (String newState) {this.nestedState = newState; vráťte to; } public PersonBuilder isFemale (boolean newIsFemale) {this.nestedIsFemale = newIsFemale; vráťte to; } public PersonBuilder isEmployed (boolean newIsEmployed) {this.nestedIsEmployed = newIsEmployed; vráťte to; } public PersonBuilder isHomeOwner (boolean newIsHomeOwner) {this.nestedIsHomeOwner = newIsHomeOwner; vráťte to; } public Person createPerson () {return new Person (nestedLastName, nestedFirstName, nestedMiddleName, nestedSalutation, nestedSuffix, nestedStreetAddress, nestedCity, nestedState, nestedIsFemale, nestedIsEmployed, nestedIsHomeOwner); }}} 

Builder môže byť ešte príjemnejší, keď je vylepšený použitím vlastných typov typov a parametrov, ako je uvedené v mojich prvých dvoch príspevkoch o probléme „príliš veľa parametrov“. Toto sa zobrazuje v nasledujúcom zozname kódov.

Person.java s vnoreným staviteľom, vlastnými typmi a objektom parametrov

balenie zásypu.príklady; / ** * Trieda osôb použitá ako súčasť demonštrácie príliš veľa parametrov. * * @author Dustin * / verejná trieda Osoba {súkromné ​​konečné meno FullName; konečná súkromná adresa; súkromné ​​konečné pohlavie; súkromné ​​konečné zamestnanieStatus zamestnania; súkromné ​​konečné vlastníctvo domu vlastník domu homeOwnerStatus; / ** * Parametrizovaný konštruktor môže byť súkromný, pretože iba môj interný tvorca * mi musí zavolať, aby som mohol poskytnúť inštanciu klientom. * * @param newName Meno tejto osoby. * @param newAddress Adresa tejto osoby. * @param newGender Pohlavie tejto osoby. * @param newEmployment Zamestnanecký stav tejto osoby. * @param newHomeOwner Stav vlastníctva tejto osoby v domácnosti. * / súkromná osoba (konečné FullName newName, konečná adresa newAddress, konečné pohlavie newGender, konečné EmploymentStatus newEmployment, konečné HomeownerStatus newHomeOwner) {this.name = newName; this.address = newAddress; this.gender = newGender; this.employment = newEmployment; this.homeOwnerStatus = newHomeOwner; } public FullName getName () {return this.name; } public Address getAddress () {return this.address; } public Gender getGender () {návrat this.gender; } public EmploymentStatus getEmployment () {return this.employment; } public HomeownerStatus getHomeOwnerStatus () {return this.homeOwnerStatus; } / ** * Trieda Builder uvedená v druhom vydaní knihy Joshua Blocha * Efektívna Java ktorý sa používa na zostavenie inštancie {@link Person}. * / public static class PersonBuilder {private FullName nestedName; súkromná adresa nestedAddress; private Gender nestedGender; private EmploymentStatus nestedEmploymentStatus; private HomeownerStatus nestedHomeOwnerStatus; public PersonBuilder (konečné celé meno newFullName, konečná adresa newAddress) {this.nestedName = newFullName; this.nestedAddress = newAddress; } verejné meno PersonBuilder (konečné meno FullName newName) {this.nestedName = newName; vráťte to; } verejná adresa PersonBuilderu (konečná adresa newAddress) {this.nestedAddress = newAddress; vráťte to; } public PersonBuilder gender (final Gender newGender) {this.nestedGender = newGender; vráťte to; } verejné zamestnanie PersonBuilder (konečné EmploymentStatus newEmploymentStatus) {this.nestedEmploymentStatus = newEmploymentStatus; vráťte to; } public PersonBuilder homeOwner (konečný HomeownerStatus newHomeOwnerStatus) {this.nestedHomeOwnerStatus = newHomeOwnerStatus; vráťte to; } public Person createPerson () {return new Person (nestedName, nestedAddress, nestedGender, nestedEmploymentStatus, nestedHomeOwnerStatus); }}} 

Posledných pár výpisov kódov ukazuje, ako sa zvyčajne používa Builder - na zostrojenie objektu. Položka v nástroji na vytváranie (položka # 2) v druhom vydaní účinnej Javy od Joshua Blocha je v kapitole o vytváraní (a ničení) objektov. Tvorca však môže nepriamo pomôcť s metódami, ktoré nie sú konštruktory, tým, že umožňuje ľahší spôsob vytvárania objektov parametrov, ktoré sa odovzdávajú metódam.

$config[zx-auto] not found$config[zx-overlay] not found