Nested Fluent Builder design pattern implemented in Java.
This design pattern is basically being used to remove need of using multi-parameter constructor like this one:
Car car = new Car("Brand", "Model", new Engine(120, EngineType.DIESEL), new Body(BodyType.SEDAN, new Trunk(500, true)));
and to remove the need of setting each field of a newly created object of the class like this:
Car car = new Car(); car.setBrand("Brand"); car.setModel("Model"); Engine engine = new Engine(); engine.setHorsePower(120); engine.setEngineType(EngineType.DIESEL); car.setEngine(engine); Body body = new Body(); body.setBodyType(BodyType.SEDAN); Trunk trunk = new Trunk(); trunk.setLiters(500); trunk.hasSpareTyre(true); body.setTrunk(trunk); car.setBody(body);
Just imagine how worse it can get if you had even more variables and objects inside objects.
Main.java
package builder; // ? 2019 TheFlyingKeyboard and released under MIT License // theflyingkeyboard.net public class Main { public static void main(String[] args) { Car car = CarBuilder .create() .setBrand("Brand") .setModel("Model") .createEngine() .setEngineType(EngineType.ELECTRIC) .setHorsePower(200) .createBody() .setBodyType(BodyType.SEDAN) .createTrunk() .setLiters(520) .hasSpareTyre(true) .build(); System.out.println(car); } }
Car.java
package builder; // ? 2019 TheFlyingKeyboard and released under MIT License // theflyingkeyboard.net public class Car { private String brand; private String model; private Engine engine; private Body body; public String getBrand() { return brand; } public void setBrand(String brand) { this.brand = brand; } public String getModel() { return model; } public void setModel(String model) { this.model = model; } public Engine getEngine() { return engine; } public void setEngine(Engine engine) { this.engine = engine; } public Body getBody() { return body; } public void setBody(Body body) { this.body = body; } @Override public String toString() { return "Car{" + "brand='" + brand + '\'' + ", model='" + model + '\'' + ", engine=" + engine + ", body=" + body + '}'; } }
Engine.java
package builder; // ? 2019 TheFlyingKeyboard and released under MIT License // theflyingkeyboard.net public class Engine { private double horsePower; private EngineType engineType; public double getHorsePower() { return horsePower; } public void setHorsePower(double horsePower) { this.horsePower = horsePower; } public EngineType getEngineType() { return engineType; } public void setEngineType(EngineType engineType) { this.engineType = engineType; } @Override public String toString() { return "Engine{" + "horsePower=" + horsePower + ", engineType=" + engineType + '}'; } }
Body.java
package builder; // ? 2019 TheFlyingKeyboard and released under MIT License // theflyingkeyboard.net public class Body { private BodyType bodyType; private Trunk trunk; public BodyType getBodyType() { return bodyType; } public void setBodyType(BodyType bodyType) { this.bodyType = bodyType; } public Trunk getTrunk() { return trunk; } public void setTrunk(Trunk trunk) { this.trunk = trunk; } @Override public String toString() { return "Body{" + "bodyType=" + bodyType + ", trunk=" + trunk + '}'; } }
EngineType.java
package builder; // ? 2019 TheFlyingKeyboard and released under MIT License // theflyingkeyboard.net public enum EngineType { DIESEL, PETROL, ELECTRIC, HYBRID }
Trunk.Java
package builder; // ? 2019 TheFlyingKeyboard and released under MIT License // theflyingkeyboard.net public class Trunk { private double liters; private boolean spareTyre; public double getLiters() { return liters; } public void setLiters(double liters) { this.liters = liters; } public boolean isSpareTyre() { return spareTyre; } public void setSpareTyre(boolean spareTyre) { this.spareTyre = spareTyre; } @Override public String toString() { return "Trunk{" + "liters=" + liters + ", spareTyre=" + spareTyre + '}'; } }
BodyType.java
package builder; // ? 2019 TheFlyingKeyboard and released under MIT License // theflyingkeyboard.net public enum BodyType { WAGON, HATCHBACK, MINIVAN, SEDAN }
Builders
CarBuilder.java
package builder; // ? 2019 TheFlyingKeyboard and released under MIT License // theflyingkeyboard.net public class CarBuilder { protected Car car = new Car(); public static CarBuilder create(){ return new CarBuilder(new Car()); } protected CarBuilder() { } protected CarBuilder(Car car) { this.car = car; } public CarBuilder setBrand(String brand){ car.setBrand(brand); return this; } public CarBuilder setModel(String model){ car.setModel(model); return this; } public EngineBuilder createEngine(){ return new EngineBuilder(car); } public BodyBuilder createBody(){ return new BodyBuilder(car); } public Car build(){ return car; } }
EngineBuilder.java
package builder; // ? 2019 TheFlyingKeyboard and released under MIT License // theflyingkeyboard.net public class EngineBuilder extends CarBuilder { public EngineBuilder(Car car) { super(car); if(car.getEngine() == null){ car.setEngine(new Engine()); } } public EngineBuilder setHorsePower(double horsePower){ car.getEngine().setHorsePower(horsePower); return this; } public EngineBuilder setEngineType(EngineType engineType){ car.getEngine().setEngineType(engineType); return this; } }
BodyBuilder.java
package builder; // ? 2019 TheFlyingKeyboard and released under MIT License // theflyingkeyboard.net public class BodyBuilder extends CarBuilder { public BodyBuilder(Car car) { super(car); if(car.getBody() == null){ car.setBody(new Body()); } } public BodyBuilder setBodyType(BodyType bodyType){ car.getBody().setBodyType(bodyType); return this; } public TrunkBuilder createTrunk(){ return new TrunkBuilder(car); } }
TrunkBuilder.java
package builder; // ? 2019 TheFlyingKeyboard and released under MIT License // theflyingkeyboard.net public class TrunkBuilder extends BodyBuilder { public TrunkBuilder(Car car) { super(car); if(car.getBody().getTrunk() == null){ car.getBody().setTrunk(new Trunk()); } } public TrunkBuilder setLiters(double liters){ car.getBody().getTrunk().setLiters(liters); return this; } public TrunkBuilder hasSpareTyre(boolean spareTyre){ car.getBody().getTrunk().setSpareTyre(spareTyre); return this; } }