I currently have a very basic Step Builder in a C# application that is created to allow all fields as optional and it is working fine for this (although this makes it not really a Step Builder).
I know that required fields can be added to the constructor as parameters but I was wondering if there is a way to add a required field as a step so that it stays as a Step Builder by handling the required fields with interfaces instead of constructor parameters.
I have a dumb class for demonstrating
class Animal {
private String type;
private String name;
public Animal(AnimalBuilder builder) {
this.type = builder.type;
this.name = builder.name;
}
public String getType() { return this.type; }
public String getName() { return this.name; }
}
Then the Step Builder (sort of) as
class AnimalBuilder {
private Builder builder;
public String type;
public String name;
public BuilderIfc start() {
this.builder = new Builder();
return this.builder;
}
public interface withTypeIfc {
BuilderIfc withType(String type);
}
public interface withNameIfc {
BuilderIfc withName(String name);
}
public interface BuilderIfc {
BuilderIfc withType(String type);
BuilderIfc withName(String name);
Animal build();
}
public class Builder : AnimalBuilder, withTypeIfc, withNameIfc, BuilderIfc {
public BuilderIfc withType(String type) {
this.type = type;
return this;
}
public BuilderIfc withName(String name) {
this.name = name;
return this;
}
public Animal build() {
return new Animal(this);
}
}
}
It works fine for these scenarios
// allow : animal has type and name
animal = new AnimalBuilder().start().withType("Dog").withName("Spanky").build();
// allow : animal has type
animal = new AnimalBuilder().start().withType("Bear").build();
But it does not work for this scenario because withType
should become required instead of optional
// do not allow : animal must have type
animal = new AnimalBuilder().start().build();
CodePudding user response:
If you want to enforce the setting of a specific option in your builder pattern, you can do this in different manners:
( List is probably not complete! )
- You can have those as a parameter to the builder-creation function.
Example for your case:
public BuilderIfc Start(string type) { /*implementation here*/ }
- You can enforce a "flow" by returning a specific interface.
// vv Next in flow _must be_ ".WithType(string)"
public IWithType Start() { /*implementation here*/ }