Designmønstre i Android – Builder

Builder

Builder-mønsteret forenkler oprettelsen af objekter på en meget ren og letlæselig måde. Det er meget nyttigt, når vi har nogle modelklasser med mange parametre. Vi kan gøre nogle af dem valgfrie eller obligatoriske, og vi tvinger ikke brugeren til at bruge en bestemt rækkefølge (som i konstruktøren). Ved at bruge Builder-mønsteret får vi en elegant kæde af metoder. Den mest almindelige anvendelse er i AlertDialog.Builder() klassen:

new AlertDialog.Builder(this)
.setTitle("Design Patterns")
.setMessage("Builder is awesome")
.create();

Hvordan kan vi oprette Builder-klassen til vores eget brug?

Builder i praksis

Lad os antage, at vi har en eller anden modelklasse til brugeren:

public class User {
private String firstName;
private String lastName;
private int age;
}

Og i stedet for at oprette objekter af denne klasse ved hjælp af konstruktorer, ønsker vi at oprette dem ved hjælp af Builder-mønsteret som her:

new User.Builder()
.setFirstName("Leonardo")
.setLastName("da Vinci")
.setAge(67)
.create();

Hvordan kan vi gøre det? For det første skal vi oprette Builder-klassen inden for User-klassen, som vil have metoderne til at opbygge vores objekt. Nøglen til at have kædemetoder er, at buildermetoder returnerer Builder-klassen. Se på eksemplet:

static class Builder {
private String firstName;
private String lastName;
private int age;
public Builder setFirstName(final String firstName) {
this.firstName = firstName;
return this;
}
public Builder setLastName(final String lastName) {
this.lastName = lastName;
return this;
}
public Builder setAge(final int age) {
this.age = age;
return this;
}
public User create() {
return new User(this);
}
}

For hver parameter har vi en setter – forskellen er, at disse metoder returnerer Builder type. Til sidst har vi en metode, der bruger konstruktør fra User-klassen og returnerer User-objektet – her er det sted, hvor vores rod holdes skjult.

Så skal vi oprette konstruktør med alle parametrene i modelklassen User :

public class User {
private String firstName;
private String lastName;
private int age;
private User(final Builder builder) {
firstName = builder.firstName;
lastName = builder.lastName;
age = builder.age;
}
}

Vigtigt her er, at User-konstruktøren er privat, så den kan ikke tilgås fra den anden klasse, og vi skal bruge Builder til at oprette nyt objekt.

Naturligvis kan vi gøre nogle af parametrene obligatoriske (for nu er alle valgfrie) ved at ændre vores create()-metode og kaste nogle undtagelser, f.eks.:

public User create() {
User user = new User(firstName, lastName, age);
if (user.firstName.isEmpty()) {
throw new IllegalStateException(
"First name can not be empty!");
}
return user;
}

Det er det hele. På denne måde skabte vi vores User.Builder() klasse!

Builder – protip

Hvis du var tålmodig nok til at komme igennem hele blogindlægget, har jeg et tip til dig vedrørende Builder-mønsteret: Du kan generere hele Builder-klassen ved hjælp af IntelliJ!

Det eneste, du skal gøre, er at placere fluebenet på konstruktøren i din klasse og vælge Refactor -> Replace Constructor with Builder i kontekstmenuen. Builder-klassen med alle metoderne vil blive automatisk genereret, klar til brug.

Du kan læse mere her: IntelliJ: Replace Constructor with Builder

Konklusion

Builder-mønsteret er en god tilgang, ikke kun til modelklasser, men til ethvert objekt, der har mere end tre eller fire parametre. Med en smule ekstra arbejde kan vi øge læsbarheden af vores kode. Designmønstre er anerkendt som den bedste praksis, så det er en stor fordel, hvis du kender nogle af dem, og Builder er et godt mønster at starte med.