In this example, the Builder pattern allows a step by step construction of various car models.
The example also shows how Builder produces can make different kinds cars using the same `building` steps.
The
Director controls the order of the construction. It knows which building steps to call to produce this or that car model. It works with builders only via their common interface.
This allows the passing of different types of builders to the
director.
The end result is retrieved from the builder object because the director can’t know the type of resulting product.
Only the Builder object knows what does it build exactly.
Let's create A package we call
components.
In
components we will place the
components need to maka car.
The
component will be
Engine,
Transmission,
TripComputer and
GPSNavigator.
The code for those componets will be:
For
Engine we have:
public class Engine {
private final double volume;
private double mileage;
private boolean started;
public Engine(double volume, double mileage) {
this.volume = volume;
this.mileage = mileage;
}
public void on() {
started = true;
}
public void off() {
started = false;
}
public boolean isStarted() {
return started;
}
public void go(double mileage) {
if (started) {
this.mileage += mileage;
} else {
System.err.println("Cannot go(), you must start engine first!");
}
}
public double getVolume() {
return volume;
}
public double getMileage() {
return mileage;
}
}
Next we create an say what type of transmission the car has.
public enum Transmission {
SINGLE_SPEED, MANUAL, AUTOMATIC, SEMI_AUTOMATIC
}
Let's also look at
TripComputer.
The code for it will be:
public class TripComputer {
private Car car;
public void setCar(Car car) {
this.car = car;
}
public void showFuelLevel() {
System.out.println("Fuel level: " + car.getFuel());
}
public void showStatus() {
if (this.car.getEngine().isStarted()) {
System.out.println("Car is started");
} else {
System.out.println("Car isn't started");
}
}
}
Let's also add a
GPSNavigator for good measure.
the code for the
GPSNavigator is:
public class GPSNavigator {
private String route;
public GPSNavigator() {
this.route = "1234 Main Street Anywhere, USA 10011";
}
public GPSNavigator(String manualRoute) {
this.route = manualRoute;
}
public String getRoute() {
return route;
}
}
Let's create a package called
cars.
In
cars we have as
enum for
Type.
public enum Type {
CITY_CAR, SPORTS_CAR, SUV
}
Now that we have the
components to create the cars.
We have two types of cars
Manual or regular
Car.
We start with the
class Car.
public class Car {
private final Type type;
private final int seats;
private final Engine engine;
private final Transmission transmission;
private final TripComputer tripComputer;
private final GPSNavigator gpsNavigator;
private double fuel = 0;
public Car(Type type, int seats, Engine engine, Transmission transmission,
TripComputer tripComputer, GPSNavigator gpsNavigator) {
this.type = type;
this.seats = seats;
this.engine = engine;
this.transmission = transmission;
this.tripComputer = tripComputer;
this.tripComputer.setCar(this);
this.gpsNavigator = gpsNavigator;
}
public Type getType() {
return type;
}
public double getFuel() {
return fuel;
}
public void setFuel(double fuel) {
this.fuel = fuel;
}
public int getSeats() {
return seats;
}
public Engine getEngine() {
return engine;
}
public Transmission getTransmission() {
return transmission;
}
public TripComputer getTripComputer() {
return tripComputer;
}
public GPSNavigator getGpsNavigator() {
return gpsNavigator;
}
}
And a
Manual type of car.
The code for
Manual is:
public class Manual {
private final Type type;
private final int seats;
private final Engine engine;
private final Transmission transmission;
private final TripComputer tripComputer;
private final GPSNavigator gpsNavigator;
public Manual(Type type, int seats, Engine engine, Transmission transmission,
TripComputer tripComputer, GPSNavigator gpsNavigator) {
this.type = type;
this.seats = seats;
this.engine = engine;
this.transmission = transmission;
this.tripComputer = tripComputer;
this.gpsNavigator = gpsNavigator;
}
public String print() {
String info = "";
info += "Type of car: " + type + "\n";
info += "Count of seats: " + seats + "\n";
info += "Engine: volume - " + engine.getVolume() + "; mileage - " + engine.getMileage() + "\n";
info += "Transmission: " + transmission + "\n";
if (this.tripComputer != null) {
info += "Trip Computer: Functional" + "\n";
} else {
info += "Trip Computer: N/A" + "\n";
}
if (this.gpsNavigator != null) {
info += "GPS Navigator: Functional" + "\n";
} else {
info += "GPS Navigator: N/A" + "\n";
}
return info;
}
}
Now let's create some
builders to build our cars.
Let's add the package
builders and let's also add an interface we called
Builder.
We place this interface the a *package* we also create called
builders.
The Builder interface defines all possible ways to configure a product.
Here is the code:
public interface Builder {
void setType(Type type);
void setSeats(int seats);
void setEngine(Engine engine);
void setTransmission(Transmission transmission);
void setTripComputer(TripComputer tripComputer);
void setGPSNavigator(GPSNavigator gpsNavigator);
}
Now let's create some car builder
CarBuilder and
CarManualBuilder.
Concrete builders implement steps defined in the common interface.
For
CarBuilder we have:
public class CarBuilder implements Builder {
private Type type;
private int seats;
private Engine engine;
private Transmission transmission;
private TripComputer tripComputer;
private GPSNavigator gpsNavigator;
@Override
public void setType(Type type) {
this.type = type;
}
@Override
public void setSeats(int seats) {
this.seats = seats;
}
@Override
public void setEngine(Engine engine) {
this.engine = engine;
}
@Override
public void setTransmission(Transmission transmission) {
this.transmission = transmission;
}
@Override
public void setTripComputer(TripComputer tripComputer) {
this.tripComputer = tripComputer;
}
@Override
public void setGPSNavigator(GPSNavigator gpsNavigator) {
this.gpsNavigator = gpsNavigator;
}
public Car getResult() {
return new Car(type, seats, engine, transmission, tripComputer, gpsNavigator);
}
}
Unlike other creational patterns, Builder can construct unrelated products, which don't have the common interface.
In this case we build a user manual for a car, using the same steps as we built a car.
This allows to produce manuals for specific car models, configured with different features.
public class CarManualBuilder implements Builder{
private Type type;
private int seats;
private Engine engine;
private Transmission transmission;
private TripComputer tripComputer;
private GPSNavigator gpsNavigator;
@Override
public void setType(Type type) {
this.type = type;
}
@Override
public void setSeats(int seats) {
this.seats = seats;
}
@Override
public void setEngine(Engine engine) {
this.engine = engine;
}
@Override
public void setTransmission(Transmission transmission) {
this.transmission = transmission;
}
@Override
public void setTripComputer(TripComputer tripComputer) {
this.tripComputer = tripComputer;
}
@Override
public void setGPSNavigator(GPSNavigator gpsNavigator) {
this.gpsNavigator = gpsNavigator;
}
public Manual getResult() {
return new Manual(type, seats, engine, transmission, tripComputer, gpsNavigator);
}
}
We now create a
Director and put it in the
director package.
Director defines the order of building steps. It works with a builder object through common Builder interface.
Therefore it may not know what product is being built.
public class Director {
public void constructSportsCar(Builder builder) {
builder.setType(Type.SPORTS_CAR);
builder.setSeats(2);
builder.setEngine(new Engine(3.0, 0));
builder.setTransmission(Transmission.SEMI_AUTOMATIC);
builder.setTripComputer(new TripComputer());
builder.setGPSNavigator(new GPSNavigator());
}
public void constructCityCar(Builder builder) {
builder.setType(Type.CITY_CAR);
builder.setSeats(2);
builder.setEngine(new Engine(1.2, 0));
builder.setTransmission(Transmission.AUTOMATIC);
builder.setTripComputer(new TripComputer());
builder.setGPSNavigator(new GPSNavigator());
}
public void constructSUV(Builder builder) {
builder.setType(Type.SUV);
builder.setSeats(4);
builder.setEngine(new Engine(2.5, 0));
builder.setTransmission(Transmission.MANUAL);
builder.setGPSNavigator(new GPSNavigator());
}
}
Let's put this altogether in the
main.
We create a
public called
Demo and in this class we place our
main method.
public class Demo {
public static void main(String[] args) {
Director director = new Director();
// Director gets the concrete builder object from the client
// (application code). That's because application knows better which
// builder to use to get a specific product.
CarBuilder builder = new CarBuilder();
director.constructSportsCar(builder);
// The final product is often retrieved from a builder object, since
// Director is not aware and not dependent on concrete builders and
// products.
Car car = builder.getResult();
System.out.println("Car built:\n" + car.getType());
CarManualBuilder manualBuilder = new CarManualBuilder();
// Director may know several building recipes.
director.constructSportsCar(manualBuilder);
Manual carManual = manualBuilder.getResult();
System.out.println("\nCar manual built:\n" + carManual.print());
}
}
Now we are ready to run this program and we get
Car built:
SPORTS_CAR
Car manual built:
Type of car: SPORTS_CAR
Count of seats: 2
Engine: volume - 3.0; mileage - 0.0
Transmission: SEMI_AUTOMATIC
Trip Computer: Functional
GPS Navigator: Functional
The Ray code is AWESOME!!!
----------------------------------------------------------------------------------------------------
Wikipedia
Find Ray on:
facebook
youtube
The Ray Code
Ray Andrade