Builder Pattern : Can our director deal with Concrete builders directly?

58 Views Asked by At

I was reading builder design pattern and have the following doubt - Why director cannot accept the concrete builder type reference ?

Suppose, we have a CarBuilder interface which implemented by 2 concrete builders SUVCarBuilder and SportsCarBuilder . We see that our Director class is like -

public class Director {

    public void constructSportsCar(Builder builder) {
        builder.setCarType(CarType.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 constructSUV(Builder builder) {
        builder.setCarType(CarType.SUV);
        builder.setSeats(4);
        builder.setEngine(new Engine(2.5, 0));
        builder.setTransmission(Transmission.MANUAL);
        builder.setGPSNavigator(new GPSNavigator());
    }
}

The methods accept Builder type rather than concrete types - SUVCarBuilder and SportsCarBuilder. Can our director not accept ConcreteBuilders types ? That way, we can even return the concrete product from director itself.

public class Director {

    public SportsCar constructSportsCar(SportsCarBuilder builder) {
        builder.setCarType(CarType.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());
        // Get the concrete product
        return builder.getSportsCar();
    }

    public SUVCar constructSUV(SUVCarBuilder builder) {
        builder.setCarType(CarType.SUV);
        builder.setSeats(4);
        builder.setEngine(new Engine(2.5, 0));
        builder.setTransmission(Transmission.MANUAL);
        builder.setGPSNavigator(new GPSNavigator());
        // Get the concrete product
        return builder.getSUVCar();
    }
}
2

There are 2 best solutions below

0
On

I think you're misunderstanding the purpose of the Builder pattern, which is to

Separate the construction of a complex object from it representation

(DP)

Thus, you wouldn't have constructSportsCar and constructSUV methods, but rather a single constructCar method:

public class Director {

    public Car constructCar(CarBuilder builder) {
        builder.setSeats();
        builder.setEngine();
        builder.setTransmission();
        builder.setTripComputer();
        builder.setGPSNavigator();
        // Get the abstract product
        return builder.getCar();
    }
}

and then you'd have one implementation of the CarBuilder interface that creates a sports car, and another one that creates the SUV.

0
On

What do the concrete builders do? In your question, they do what the base builder does.

If the concrete builders do some internal settings on the product, then they use some part of the base builder's code and some code will be duplicated.

If you pass the base builder to the concrete builders to comply with DRY, the concrete builders will do the same as the Director does.

So there is no need to pass concrete builders to the Director. Using concrete builders in the Director makes your code complicated with no benefits. It's better to use the base builder and let the director choose what to set.

In fact, the director knows what to set, this knowledge does not belong to the builder. Builders only know how to set, not what to set.