Het stapsgewijze constructorpatroon
Zowel statische fabrieken als constructors zijn moeilijk om goed mee om te gaan wanneer er veel parameters zijn. Stel dat een klasse 6 velden heeft en we constructors willen die 2 parameters, 3 parameters, etc. accepteren. In dat geval kunnen we het stapsgewijze constructorpatroon gebruiken, zoals hieronder te zien is.
Maar zelfs dit wordt lastig te lezen wanneer er veel parameters zijn. Het is dan moeilijk te onthouden wat elke parameter betekent en parameters van hetzelfde type kunnen door elkaar gehaald worden.
Het Java Beans-patroon
Het Java Beans-patroon maakt een object aan met een parameterloze constructor en gebruikt vervolgens setter-methoden om de waarden van de gewenste parameters in te stellen.
Het Java Beans-patroon maakt het mogelijk om, zelfs met veel parameters, objecten te maken zonder dat er verwarring ontstaat. Maar om een object te maken moeten we meerdere setter-methoden aanroepen en totdat het object volledig is aangemaakt, is de consistentie verbroken. Dit zorgt ervoor dat de klasse niet immutabel kan zijn.
Het Builder-patroon
Het Builder-patroon combineert de robuustheid van het stapsgewijze constructorpatroon met de leesbaarheid van het Java Beans-patroon. Dit patroon wordt dan ook het meest gebruikt.
In plaats van dat de client zelf het object aanmaakt, roept hij eerst een constructor aan met alleen de verplichte parameters om een Builder-object te krijgen. Vervolgens gebruikt hij de setter-achtige methoden die door het Builder-object aangeboden worden om de gewenste optionele parameters in te stellen. Tot slot roept hij de parameterloze build()-methode aan om het gewenste object te verkrijgen.
De constructor van de Builder-klasse neemt alleen de verplichte parameters aan en de overige optionele parameters worden met behulp van setter-achtige methoden ingevuld. Tot slot wordt via de build()-methode een compleet NutritionFactsWithBuilderPattern-object aangemaakt. De NutritionFactsWithBuilderPattern-klasse is immutabel en de setter-achtige methoden van de builder retourneren de builder zelf, waardoor ze in een keten aangeroepen kunnen worden. Deze manier van aanroepen wordt ook wel een fluent API of method chaining genoemd.
Voor de client is het Builder-patroon een makkelijke en leesbare manier om code te schrijven.
Het Builder-patroon past goed bij hiërarchisch ontworpen klassen
De Pizza.Builder-klasse is een generieke klasse die gebruik maakt van recursieve typebinding. Met de abstracte methode self() kunnen subklassen method chaining gebruiken zonder dat type casting nodig is. Subklassen kunnen deze abstracte methode laten retourneren naar zichzelf.
Laten we nu kijken naar de subklassen New York Pizza en Calzone Pizza, om de flexibiliteit van het Builder-patroon te zien.
De build()-methode van elke subklasse retourneert een concreet subklasse-object. De functionaliteit waarbij een methode van een subklasse een ander type retourneert dan de methode van de superklasse, wordt covariante return typing genoemd. Met deze functionaliteit hoeft de client geen type casting te doen.
De client kan de enums van Pizza en de enums van de subklassen door elkaar gebruiken en met de juiste methoden het object afmaken.
Nadelen van het Builder-patroon
- Er moet een Builder-object aangemaakt worden.
- De code wordt wat langer.
Samenvatting
Als een constructor of statische fabrieksmethode veel parameters moet verwerken, dan is het Builder-patroon een optie die je kunt overwegen.
Bronnen
- Effective Java
Reacties0