You can use a Step Builder if you have many mandatory parameters. In short: you define an interface for every single mandatory parameter and a builder method returns the next mandatory builder interface or the builder itself for optional methods. The builder remains a single class which implements all the interfaces.
interface StepB {
StepBuilder b(String b);
}
interface StepA {
StepB a(String a);
}
final class StepBuilder implements StepA, StepB {
private String a;
private String b;
private String c = "";
private StepBuilder() {
}
static StepA with() {
return new StepBuilder();
}
// mandatory, from StepA
@Override
StepB a(String a) {
this.a = a;
return this;
}
// mandatory, from StepB
@Override
StepBuilder b(String b) {
this.b = b;
return this;
}
// optional
StepBuilder c(String c) {
this.c = c;
return this;
}
Product build() {
return new Product(a, b, c);
}
}
Usage:
StepBuilder.with().a("hello").b("world").build();
// or with the optional parameter c
StepBuilder.with().a("hello").b("world").c("!").build();
Keep in mind that I named the class StepBuilder
only to make it clear in my explanation. It would be better to give it a name reflecting some aspect of the respective domain. Example:
Url.with().host("example.com").port(81).path("some/where").query("status=1").build()
Languages like Kotlin and Scala are more convenient here, since they offer named parameters with default values.