Vilket problem löser en byggmästare?

Byggmönstermönstret försöker lösa problemet med stora konstruktörer när ett objekt har många obligatoriska instansvariabler. När detta är fallet måste du ofta ta dig tid att studera konstruktören när du försöker ta reda på vilka parametrar som går i vilken ordning. Om du dessutom har sekvenser av identiskt typade parametrar (t.ex. fyra strängobjekt i rad) kan det leda till mycket subtila buggar eftersom kompilatorn inte kommer att klaga på felaktig positionering eftersom allt man vet är att den har värden av rätt typ.

Tänk på exemplet nedan för att beteckna en person. När du försöker förklara en ny instans av typen Person måste du känna till beställningen av namnen liksom ordningen på vikt och höjd. När du tittar på exempeldeklarationen kan du se att det är mycket svårt att sluta sig till vilket av de två siffrorna, 80, 0 eller 73, 0, som motsvarar vikten eller höjden.

Tänk också på en person med namnet "John Joe James", och ja det är namnet på någon jag kände på gymnasiet. Med ett namn som det som är förnamn, mellannamn och efternamn? Det skulle vara extremt svårt att dra slutsatsen från en enkel konstruktör utan att behöva ta extra tid för att undersöka källkoden för Person-konstruktören.

Föreställ dig nu exemplet med en klass som är tänkt att representera uppgifterna på en näringsmärkning för mat, du kanske måste ha numeriska värden för 20 eller fler näringsämnen som protein samt kalorier och annan information som allergivarningar. Med så mycket information som krävs blir det oundvikligt att ett misstag kommer att hända minst en gång när man förklarar en instans med en 20 eller fler parameterkonstruktör, särskilt när så många kommer att vara enkla nummer.

Ett myrstandardsexempel på en Java-klass med sex konstruktöraggregat.
Att förklara en instans av klassen är smärtsamt eftersom du måste komma ihåg argumentställningar. Till exempel, vilken är höjd och vilken är vikt?

En av de vanliga korrigeringarna för detta problem som utvecklare försöker använda är att förklara Person-objektet med en tom konstruktör och sedan ringa alla inställare på objektet omedelbart efteråt. Detta löser problemen med att känna till parametrarna och ett exempel ges nedan.

Det här är en dålig idé eftersom det betyder att objektet kan befinna sig i ett inkonsekvent tillstånd under kedjan av bosättare men fortfarande kan användas. Om jag av misstag lägger till ett samtal till en annan metod halvvägs genom listan över bosatta kan det få oavsiktliga konsekvenser. Vi vill att objektet ska vara i ett giltigt tillstånd när vi skapar det. Detta har också konsekvenser för samtidig kod där två eller flera trådar kan fungera på ett visst objekt, vad händer om tråd A krävde att ett värde skulle ställas in som tråd B egentligen inte har ställt in? Misslyckande, det är vad.

Ett exempel på att använda en tom konstruktör följt av inställare för att göra parameternamn mer tydliga.

Byggmästarmönstret erbjuder det bästa från båda världar; ger dig ett komplett objekt vid retur (så länge alla fält är inställda) och förhindrar dig från att behöva komma ihåg positionen för olika argument. Låt oss dyka in till ett exempel.

Tänk på en byggare när du står inför många konstruktionsparametrar.

- Effektiv Java av Joshua Bloch

Exempel på byggmönster

Nedan ser du koden som krävs för att skapa en byggare för Person-objektet. Alla argument för detta exempel har gjort att de är valfria, men det är enkelt att göra vissa argument obligatoriska genom att skapa en konstruktör för Builder-objektet med de obligatoriska argumenten och ha dem som parametrar för metoden för statisk byggare () . Detta avslöjar en svaghet i byggmönstret; det skalar väl till många valfria argument och skalas inte bra med obligatoriska argument.

Du kommer att märka att vår klassdeklaration för Person-klassen just har blivit mycket större, och nu när vi lägger till en ny instansvariabel till Person (till exempel att lägga till skostorlek) måste byggaren också uppdateras. Det här är en annan svaghet i byggmönstret, det kräver pannplattkod och underhåll av pannplattan. Men senare i den här artikeln kommer jag att visa dig hur du förvandlar all den här pannplattan till en enda kommentar som hanterar underhåll åt dig.

Personklassen utvidgades för att följa byggmönstret.

Som ni kan se nedan möjliggör byggmönstret mycket trevligare objektdeklarationer där varje argumentnamn uttryckligen ges massivt för att minska risken för oavsiktliga positioneringsfel som leder till svåra att hitta buggar.

Det kan sägas att objektförklaringarna också är mer behagliga för läsarnas öga, de flödar mycket trevligare än långa konstruktörer.

Detta visar den största styrkan i byggmönstret, det möjliggör en tydlig parameterinställning så att läsaren aldrig behöver gå till källkoden för personklassen för att undersöka konstruktören. Även om du spenderade lite extra tid på att skriva byggnadsimplementeringen sparar det otaliga timmar i raden när du inte behöver söka efter subtila buggar orsakade av bytteparametrar.

Att förklara en personinstans med byggmästaren är mycket renare, inte mer gissa vilket argument som går där.

Fördelarna med byggmönstret

  • Inte mer oroande för vilket argument som går i vilken position, byggmönstret är tillräckligt ordentligt för att säkerställa att du alltid vet vilket argument du arbetar med.
  • Perfekt för när ett objekt har många valfria argument.

Nackdelar med byggmönstret

  • Skalas inte bra för många obligatoriska argument.
  • Mycket av pannplåtkoden som behövs för implementering som behöver uppdateras när originalobjektet uppdateras.

Minska kokkärlet

Byggmönstret är perfekt för att göra objekt med många instansvariabler lättare att konstruera men det kommer med en hel del pannplåtkod. Denna pannplatta gör inte bara objektdefinitionen mer trångt och svårare att läsa igenom utan den måste också upprätthållas, om en instansvariabel läggs till eller tas bort måste byggaren också uppdateras för att återspegla den förändringen. Skulle det inte vara trevligt om det fanns ett sätt att ta bort pannplattan OCH automatiskt uppdatera byggaren baserat på instansvariablerna? Lombok ger exakt att med @Builder-anteckningen täcker min introduktion till Lombok-artikeln detta och många fler detaljer.

Detta har exakt samma funktionalitet som det föregående exemplet med byggmästare, utan kokkärlskod att oroa dig för tack vare Lombok.
  • Introduktion till Lombok del 1
    Alla hatar pannkodskoden, särskilt i Java. Den här artikeln visar hur du kan stänga av repetitiva konstruktörer, getters och seters med hjälp av det anteckningsbaserade biblioteket i Lombok.

Builder Design Pattern Video Tutorial

Slutsats

Idag tittade vi på hur byggmönstret kan hjälpa till att minska felen och ögonskadande koden förknippade med stora konstruktörer. Vi diskuterade hur även om byggmästarmönstret ger stor nytta för objektskaparen, det lägger till arbete för objektförfattaren när det gäller att underhålla byggaren. Slutligen visade jag er att allt underhåll och pannplatta kan hanteras med en enkel Lombok-kommentar @Builder. Lycklig kodning!