I am constructing a car class that has an engine, gearbox, clutch etc.
I don't want a bloated constructor that takes 7 parameters, so I decided to use the builder pattern.
All the parts are required.
However, how do I make the user of the Car class use all the parts' setters, as they are all mandatory?
Throw exceptions?
public class Car {
private Engine engine;
private Chassis chassis;
private GearBox gearBox;
private Coupe coupe;
private Exterior exterior;
private Interior interior;
private Clutch clutch;
public Car(Builder builder) {
engine = builder.engine;
chassis = builder.chassis;
gearBox = builder.gearBox;
coupe = builder.coupe;
exterior = builder.exterior;
interior = builder.interior;
clutch = builder.clutch;
}
public static class Builder {
private Engine engine;
private Chassis chassis;
private GearBox gearBox;
private Coupe coupe;
private Exterior exterior;
private Interior interior;
private Clutch clutch;
private Car build() {
return new Car(this);
}
public Builder setEngine(#NonNull Engine engine) {
this.engine = engine;
return this;
}
public Builder setChassis(#NonNull Chassis chassis) {
this.chassis = chassis;
return this;
}
public Builder setGearBox(#NonNull GearBox gearBox) {
this.gearBox = gearBox;
return this;
}
public Builder setCoupe(#NonNull Coupe coupe) {
this.coupe = coupe;
return this;
}
public Builder setExterior(#NonNull Exterior exterior) {
this.exterior = exterior;
return this;
}
public Builder setInterior(#NonNull Interior interior) {
this.interior = interior;
return this;
}
public Builder setClutch(#NonNull Clutch clutchs) {
this.clutch = clutchs;
return this;
}
}
}
I want the user so call ALL of the builder setters, not an optional subset of them. How do I do that?
Is there another way to construct a car without having a huge constructor that takes so many parameters?
EDIT: I looked at The builder pattern and a large number of mandatory parameters but there is no solution there that prevents huge constructors.
Builders are for things where lots of parts are optional or you have many different configurations. The build() method then makes sure that the specific configuration works. A HTML builder makes sense, a string builder not so much.
If there are no optional parts, you have these options:
Get rid of the builder and use a constructor that requires all parts. Classic solution, least readable and hard to extend.
You can throw an exception in the build() method for each missing part. That's a lot of code to write and kind of goes against the pattern.
You can add methods with more than a single argument to the builder. That's a mix of the two above. You're still using the builder pattern (so you can easily add more configurations later) but your API also communicates more clearly which parts are mandatory.
As an example, you might get an engine in the future which already contains the gearbox or which requires a specific gearbox (i.e. when you use this engine, you also select the gearbox). To implement this, you'd create a second builder method which just asks for the engine and determines the gearbox automatically.
Use a factory with protected methods which build the parts. The factory will make sure all parts are supplied to the car. If you want to replace a part, you can override the protected method. This works well if you have lot of defaults and only 2-3 useful configurations.
Use several builders. Instead of build everything from individual screws, create your car from larger building blocks: propulsion, interior, body. Create your car from those three with a constructor (three parameters is good). Now you can use three builders to create those three. Try to find a balance between required and optional elements.
Chain builders as explained by mlk below. This forces the user to fill in all parts (since you can only call the build() at the end of the chain). Main drawbacks here are: A lot of code to write and hard to follow from the user perspective since the code is spread over many classes. jOOQ is an example here; the project implements the SQL syntax as a chain of builders.
Remember what the builder pattern tries to solve: They make it easy to add more parts since all existing code doesn't need to change if the new part is optional. If the new part is mandatory, the builder pattern becomes a liability: With a huge (unreadable) constructor, you get compile errors in all places that needs fixing. The builder will fail at runtime in this case; you need an IDE to find all the places which need fixing.
If the primary reason for this is to have a fluent API rather than removing a bloated constructor then you could chain builders together:
class Engine {}
class Door {}
class Car {
Car(Engine engine, Door door) {
}
}
class CarBuilder {
private Engine engine;
public CarWithEngineBuilder withEngine(Engine engine) {
this.engine = engine;
return new CarWithEngineBuilder();
}
class CarWithEngineBuilder {
private Door door;
public CarWithEngineAndDoor withDoor(Door door) {
this.door = door;
return new CarWithEngineAndDoor();
}
class CarWithEngineAndDoor {
public Car build() {
return new Car(engine, door);
}
}
}
}
class TestStuff {
{
Car c = new CarBuilder().withEngine(new Engine()).withDoor(new Door()).build();
}
}
Or if your main concern is the size of the constructor, maybe the constructor is telling you something, and you could look at the class and see is some parts are logically "together". I.e. are Engine, Gears & Brake are one part of larger component? Should the car be DriveSystem and Chassis (which includes an Exteriorand Interior). Then constructor for Car has a manageable number of parameters, as does DriveSystem and Chassis?
If you look to the builder pattern, you can find out, that there is important thing, which you do not have, and it is Director. And also Builder interface, that defines all the required methods.
Director should call all methods required on interface builder (in your case "build engine, build coupe etc."). The class implementing the Builder interface must override all methods or the code does not even compile.
Related
I am using the Builder Pattern since time ago, but these days one of my collegues reach me with a question to which I never thought about, and is about the #newBuilder() function in the Builder Pattern.
I've seen in several forums, tutorials, and even APIs, that when using the Builder Pattern, a structure like this is usually used:
Car car1 = new CarBuilder().newBuilder().twoDoors().fourWheels().build();
Usually, inside of the #newBuilder() function, there is a code like this:
public static CarBuilder newBuilder(){
return new CarBuilder();
}
The question is, why should be needed a #newBuilder() function in the Builder class? Is it a good practice to have it, or is needed only when overloading is applied? I mean, just in the cases where I need to overload the #newBuilder() having 2 or 3 different #newBuilder() functions with different parameters.
What if I will have only one #newBuilder() function in the Builder class? Should I implement it, or can I avoid it and do something like:
Car car1 = new CarBuilder().twoDoors().fourWheels().build();
The question of my colleague was: If I implement the #newBuilder() function, am I falling in redundancy with the first example if I will only have one #newBuilder() function in my Builder class?
What you think about this? Should I remove it or it is justified to have the #newBuilder() function despite of I have only one implementation of it without overloading?
Thanks!
Note that this:
Car car1 = new CarBuilder().newBuilder().twoDoors().fourWheels().build();
Is definitely redundant, but not because the newBuilder() method exists. The problem is your code is essentially this:
CarBuilder builder1 = new CarBuilder();
CarBuilder builder2 = builder1.newBuilder();
Car car1 = builder2.twoDoors().fourWheels().build();
In other words, you're creating two instances of CarBuilder. Also, you're calling a static method on an instance reference, which is frowned upon. With your current setup, your code should be either:
Car car1 = new CarBuilder().twoDoors().fourWheels().build();
OR:
Car car1 = CarBuilder.newBuilder().twoDoors().fourWheels().build();
Which style you choose is up to you. However, if you choose to use the second approach (the static factory method newBuilder()), then typically the builder's constructor is made private, or at least package-private, so that new CarBuilder() cannot be used by external code.
So, I would say "no", having newBuilder() is not redundant in and of itself, as long as you use it correctly. It's simply an alternative way of creating a builder instance without calling the constructor directly. Note using the static factory method approach may aid in readability, because you can name the method something more descriptive. You may not see that advantage unless you have a significant number of different factory methods with different semantics, however.
Another thing to consider is where to place the newBuilder() static method. If CarBuilder and Car are extremely coupled, then many developers will put the static method in the Car class instead of the CarBuilder class (if not just nest the latter in the former).
For example:
package sample;
public final class Car {
public static CarBuilder newBuilder() {
return new CarBuilder();
}
private final int numberOfDoors;
private final int numberOfWheels;
Car(CarBuilder builder) {
this.numberOfDoors = builder.numberOfDoors;
this.numberOfWheels = builder.numberOfWheels;
}
// getters and setters omitted for brevity
}
package sample;
public final class CarBuilder {
private int numberOfDoors; // should initialize to sensible default
private int numberOfWheels; // should initialize to sensible default
CarBuilder() {}
public CarBuilder twoDoors() {
numberOfDoors = 2;
return this;
}
public CarBuilder fourWheels() {
numberOfWheels = 4;
return this;
}
public Car build() {
return new Car(this);
}
}
Which could then be used like so:
Car car1 = Car.newBuilder().twoDoors().fourWheels().build();
I am trying to build an object that gets its data from external APIs. I will try to explain it with an example:
First of all, I get a POST body in my API to create an object:
class CarRequestBody {
private String colorId;
private String engineId;
//Constructors, etc.
}
Then with this info I need to build a detailed instance of the Car. Feeding the data from external services:
ColorDetails color = colorApiClient.getColor(colorId);
EngineSpecifications engine = engineApiClient.getEngine(engineId);
And finally I build my Domain Object with all this info.
So I would like to know what is the best practice in order to build the instance. I have thought in 3 different ways:
1 - A method in CarService like this:
public Car createCar(CartRequestBody body) {
ColorDetails color = colorApiClient.getColor(body.getColorId);
EngineSpecifications engine = engineApiClient.getEngine(body.getEngineId);
Car car = new Car(color, engine);
}
2 - Feed the data in the constructor:
public Car(CarRequestBody body) {
this.color = colorApiClient.getColor(body.getColorId);
this.engine = engineApiClient.getEngine(body.getEngineId);
}
3 - In the getters of the domain class:
class Car {
private ColorData color;
private EngineSpecifications engine;
//Constructor
public ColorData getColor() {
if (color == null){
return colorApiClient.getColor(colorId);
}
return this.color;
}
....
}
Is there some design pattern for this scenario?
If you aim to keep your design clean, your domain class Car should be aware only of the objects like ColorData and EngineSpecificationsonly that it requires to function properly.
It's not a good idea to inject apiClient into the Car class because it's unrelated to its functionality and will increase coupling.
Also, what if an API call will fail, do you really want to add the plumbing code that will handle this scenario into a constructor?
Similarly, I don't see an advantage in defining a constructor that expects CarRequestBody.
The cleanest approach will be to keep the constructors of your domain classes simple and free from objects that are not needed for them to act. And if you want to generalize the process of instantiation of these domain classes, you can introduce utility methods that will take care of it.
I would suggest using the Builder design pattern.
Here you can see the code-
Car.java
public class Car{
private ColorDetails colorDetails;
private EngineSpecifications specifications;
private Car(CarBuilder builder){
this.colorDetails = builder.colorDetails;
this.specifications = builder.specifications;
}
public static class CarBuilder {
private ColorDetails colorDetails;
private EngineSpecifications specifications;
public CarBuilder withColor(ColorDetails colorDetails) {
this.colorDetails = colorDetails;
return this;
}
public CarBuilder withSpecifications(EngineSpecifications
specifications) {
this.specifications = specifications;
return this;
}
public Car build() {
Car car = new Car(this);
return car;
}
}
}
// Client code
public class Client{
ColorDetails color = colorApiClient.getColor(colorId);
EngineSpecifications engine = engineApiClient.getEngine(engineId);
Car car = new Car.CarBuilder()
.withColor(color)
.withSpecifications(engine)
.build();
}
What would be wrong with a simple constructor?
I don't know Java, but would be this in C#:
class Car {
...
public Car(Color color, Engine engine) {
... // set properties with the parameters
}
}
Oh, and if you want to do some Decoupling, please don't use the same objects in your Domain as in API. So you will need some kind of Mapper object.
// EDIT
Since you are using a request, you could make a requesthandler class. If you use Inversion of Control or a Mediator you could connect the request to the handler in that way. So you could look into those design patterns. You could also look into Clean Architecture to separate your domain code from external systems (API's in this case)
public CarRequestHandler : IRequestHandler<CarRequest> {
public CarRequestHandler(IColorRepository colorRepository, IEngineRepository engineRepository) {
this.colorRepo = colorRepository; //etc.}
public Handle(CarRequest request) {
// call repositories with the ids and create the domain object and stuff
}
}
I am designing a java system where users can define some rules in a fluent style.
Rules have many properties, which are partly mutually exclusive.
We use a builder pattern with validation for this.
To make the system easier to use, we want to introduce a StepBuilder, to guide the user to all necessary steps.
There are different types of rules, but all share some common properties.
Current System:
abstract BaseBuilder<T extends BaseBuilder<T>> {
protected String property1;
protected String property2;
protected String property3;
abstract Rule build();
public T withProperty1(String data) {
this.property1 = data;
return this;
}
public T withProperty2(String data) {
this.property2 = data;
return this;
}
public T withProperty3(String data) {
//this should only be possible if property2 is not set or similar logic
this.property3 = data;
return this;
}
}
//there are a few others like this e.g. SpecialBuilder1-10
class SpecialRuleBuilder extends BaseBuilder<SpecialBuilder> {
protected String special1;
protected String special2;
public T withSpecial1(String data) {
this.special1 = data;
return this;
}
public T withSpecial2(String data) {
this.special2 = data;
return this;
}
#Override
Rule builder() {
return new SpecialRule(property1, property3, special1, special2, ....);
}
static SpecialRuleBuilder builder() {
return new SpecialRuleBuilder();
}
}
class BuilderTest() {
//User can set anything, no steps are enforced at compile time
Result result = SpecialBuilder.builder()
.property1("some")
.special2("thing")
.build();
}
How can we use a StepBuilder including a hierarchy (parent class), so the user cannot get to the same step twice cannot accidentally go back to a previous base step and set some mutually exclusive properties again.
Ideally the user should not be aware of all the special builders and have the same entry point and guided steps. For example:
Result result = GeneralBuilder.builder()
.withBaseProperty1("asdas") <-- Step 1
.withBaseProperty2("asd") <-- Step 2, Step 3 is now not visible, continue with all possible special options
.withSpecial1("asd") <-- no we are in the step of one concrete builder, and should not get "out" again, not even to the base methods
I know how to define the interface steps, I just dont know how to include all possible starting steps of the special builders at the end of the base steps, since the higher interface/class should probably not rely on the lower parts of the hierarchy.
Is this somehow possible?
This is a bad idea; the sheer amount of code you need to write is staggering. Also, whilst the appeal of a guided 'auto-complete' experience in an IDE is obvious, realize that sometimes builders are used in a more fluent (heh) fashion: Some code makes a builder, sets half the stuff, and then returns the builder so that other code can pick up where it left off. Or, a utility method that takes a builder as param, and sets a few things on it. These use cases become awkward to impossible when you go down this path. So, you spend a ton of time writing this code and it's not even a clean win, API-wise!
If you want to ignore my advice and do it anyway, well, okay. Your funeral. A warned person counts for two, and all that. It looks like this:
public interface BridgeBuilder1 {
public BridgeBuilder2 name(String name); // mandatory
}
public interface BridgeBuilder2 {
public BridgeBuilder3 buildYear(int year); // mandatory
}
public interface BridgeBuilder3 {
// one of these two is mandatory, and they are mutually exclusive.
public BridgeBuilder4 lanes(int lanes);
public BridgeBuilder4 width(int widthInM);
}
public interface BridgeBuilder4 {
// optional stuff, and the build itself.
public BridgeBuilder4 color(Color c);
public BridgeBuilder4 country(String name);
public Bridge build();
}
// intentionally private class! Should be an inner class
// of your public Bridge class.
private static class BridgeBuilder implements BridgeBuilder1, BridgeBuilder2, BridgeBuilder3, BridgeBuilder4 {
private String name;
public BridgeBuilder2 name(String name) {
this.name = name;
return this;
}
// the fluent, chaining 'setters' for _ALL_ properties here.
// Match the return types exactly to how they
// are defined in the interfaces.
public Bridge build() {
return new Bridge(name, year, ....);
}
}
...
public class Bridge {
Bridge(String name, ...) {
// a package private constructor.
}
public static BridgeBuilder1 builder() {
return new BridgeBuilder();
}
}
That should be sufficient to highlight how this works.
But don't.
NB: The actually good solution is to enshrine the notion of a builder into the editor/lang tooling itself. An eclipse or intellij plugin, in other words. Annotations can be used to identify everything (annotate a builder() method to indicate it makes a builder, annotate a class that it is a builder class, etc), then annotate each method in a builder as being optional or not, and as being multiple or not (imagine a builder method that is intended to be invoked multiple times to e.g. fill a list). Armed with that info a plugin can 'fix' the auto-complete dialog to skip all the crap from j.l.Object, and to show all mandatory fields in bold, all already-set stuff greyed out, all optionals in normal colour, and the build method greyed out until all mandatories are set, and bold once they are. That's the real solution. I invite anybody to write these plugins instead of wasting time maintaining this ridiculous-length API extravaganza to create a hampered take on the idea.
I had a question regarding the "Builder Pattern" covered in "Effective Java". Do we need a .build() method for it to correctly implement the pattern? For instance, let's say that we have the following class:
public class CoffeeDrink {
private int numEspressoShots;
private short milkType;
private boolean withWhip;
private CoffeeDrink() {
}
public static CoffeeDrink buildNewDrink() {
return new CoffeeDrink();
}
public CoffeeDrink withEspresso(int n) {
this.numEspressoShots = n;
return this;
}
public CoffeeDrink withMilkType(shot t) {
this.milkType = t;
return this;
}
public CoffeeDrink withWhip() {
this.withWhip = true;
return this;
}
}
And then how we use it:
CoffeeDrink c = CoffeeDrink.buildNewDrink()
.withEspresso(2)
.withMilkType(2)
.withWhip();
Would this still be valid if I don't have a static inner Builder class? I guess that one of the advantages is that it holds off from creating a new CoffeeDrink object until the method .build() is called, but I'm still creating a Builder object. Just seeking some clarifications.
No, this is not the Builder pattern. It's valid Java, and it will compile and run. But your buildNewDrink() method, whether it's called build() or buildNewDrink() or something else, is just a simple Factory Method that creates a CoffeeDrink. Those other methods are like setter methods that happen to return themselves.
The static nested Builder class is necessary. While holding off on creating the class instance, it can perform validation logic to ensure that an invalid object is not created. I'm not sure that there is an invalid state to a CoffeeDrink as you have it, but if it did, with your code, it would be possible to create a CoffeeDrink and have it in an invalid state after it was created, but before other methods were called. The Builder pattern eliminates this possibility by validating the data before building the instance. It also eliminates the need for constructor explosion, where lots of constructors with all possible combinations of parameters are needed, to cover all possible cases.
According to the GoF reference, build() isn't required. The original reference doesn't use chaining, and there is a getResult() step at the end of the Director.construct() method. The Director class takes care of encapsulating the build process, so Clients don't need to worry if they're building things correctly. It's the responsibility of the Director.
Here's the sequence diagram from the GoF reference on Builder:
Im building a relatively large object-oriented program. I have a class called AerodynamicCalculator that performs numerous calculations and distributes the results around the system. My main concern is that my constructor signature is getting larger and larger as I add mor parameters to it.
As shown below I already have nine object references being passed into this constructor, but I need a further seven. Am I correctly creating this object? My understanding is that you pass the associated object references to the constructor and assign the class'es local variable to the object references. If this is the case the only way to get my class properly initialized with all the required objects is to pass them to the constructor, which is leading to a very long signature.
public AreodynamicCalculator(AircraftConfiguration config, AileronOne aOne,
AileronTwo aTwo, ElevatorOne eOne, ElevatorTwo eTwo, Rudder r,
Rudder rr, RateGyros rG) {
// ...
}
Any advice on this approach would be very helpful, thanks in advance.
As mentioned - this may be a sign your class is doing too much, however, there is a commonly used 'solution' to this problem.
The builder pattern is often used in this situation, but it's also very useful when you have many constructors with different arguments, the builder is good because it makes the meaning of the arguments clearer, particularly when boolean literals are used.
Here is the builder pattern, the way this works is like this:
AreodynamicCalculator calc = AreodynamicCalculator.builder()
.config(theAircraftConfiguration)
.addAileron(aileronOne)
.addAileron(aileronTwo)
.addElevator(elevatorOne)
.addElevator(elevatorTwo)
.addRudder(rudderOne)
.addRudder(rudderTwo)
.build()
Internally, the builder will store all these fields, and when build() is called it will call a (now private) constructor that takes these fields:
class AreodynamicCalculator {
public static class Builder {
AircraftConfiguration config;
Aileron aileronOne;
Aileron aileronTwo;
Elevator elevatorOne;
Elevator elevatorTwo;
...
public Builder config(AircraftConfiguration config) {
this.config = config;
return this;
}
public Builder addAileron(Aileron aileron) {
if (this.aileronOne == null) {
this.aileronOne = aileron;
} else {
this.aileronTwo = aileron;
}
return this;
}
// adders / setters for other fields.
public AreodynamicCalculator build() {
return new AreodynamicCalculator(config, aileronOne, aileronTwo ... );
}
}
// this is the AircraftConfiguration constructor, it's now private because
// the way to create AircraftConfiguration objects is via the builder
//
private AircraftConfiguration config, AileronOne aOne, AileronTwo aTwo, ElevatorOne eOne, ElevatorTwo eTwo, Rudder r, Rudder rr, RateGyros rG) {
/// assign fields
}
}
Similarly to using the builder pattern, suggested in daveb's response, you can use a Dependency Injection framework like Spring.