Builder Pattern : Why does the Director construct the object?
Asked Answered
B

4

6

I am learning the Builder Pattern

In the above link (Java example), I noticed that the Builder offers interface to construct multiple components. Along with invoking them, we call the getProduct() as well.

The point I don't understand is that why does the Director need to call all those component-construct methods one by one and get the result in the end.

     /** "Director" */
 class Waiter {
    private PizzaBuilder pizzaBuilder;


public void setPizzaBuilder(PizzaBuilder pb) { pizzaBuilder = pb; }
public Pizza getPizza() { return pizzaBuilder.getPizza(); }

public void constructPizza() {
   pizzaBuilder.createNewPizzaProduct(); 
   pizzaBuilder.buildDough(); // construct component 1
   pizzaBuilder.buildSauce(); // construct component 2
   pizzaBuilder.buildTopping();  // construct component 3
}

}

Why don't we include the code for constructing components 1, 2, 3 in the ConcreteBuilder class it self rather than in the Director, and in fact eliminate the Director layer.

I understand that the above approach might turn the Builder pattern into something else, but I don't get why the Director is doing the job step-by-step. What's the benefit? If there are multiple directors, there will be duplicate code, right? I might not be understanding the motive behind the execution of the Builder pattern...

UPDATE : Does the Builder pattern focus on offering customizable-component-selection while creating a larger complex object? Otherwise, as of now, I don't see the point in introducing an additional layer, the Director.

Even if that's the case, Decorator pattern might be a better idea to accomplish the same by dynamically customizing the components. Somewhere I'm missing the point behind the Builder.. :(

Boney answered 9/3, 2013 at 4:10 Comment(1)
Indeed a good question, even after reading answers I still don't get why we need director class. It it can provide custom implementation, then it makes sense. Otherwise no pointEncode
K
8

The purpose of the Director class is to encapsulate the algorithm for creating an object, i.e. separate the code for the construction logic from the code for the parts that actually make up the object. Without the Director class your Builder class would be bulkier and less modular, thus more difficult to maintain and less reusable.

The Wikipedia example you are referring to is rather simplistic. With complex objects, the construction mechanism is usually much more involved, and the Director does not necessarily call the Builder methods one-by-one and in the order they are defined. Consider, for instance, the Cake class: it may have parts ChocolateLayer, CreamLayer and Strawberry. The Builder would define the three methods for building these three parts in this particular order, however the constructCake() method in your Director class might look something like this:

public void constructCake() {
   CakeBuilder.createNewCakeProduct(); 
   CakeBuilder.buildChocolateLayer(); 
   CakeBuilder.buildCreamLayer(); 
   CakeBuilder.buildChocolateLayer(); // 2nd call of the same Builder method
   int totalStrawberries = 3 + new Random().nextInt(2);
   for (int i = 1; i <= totalStrawberries; i++) 
      CakeBuilder.buildStrawberry(); // put some strawberries on top
   // Please don't try this recipe at home! 
}

As for the differences between the Builder and the Decorator, you might check the Builder Vs Decorator pattern question.

Kempe answered 9/3, 2013 at 20:56 Comment(4)
To me this seems like a correct answer to the initial question. We can have two Directors, one would be HiltonCookDirector, the other FourSeasonsCookDirector, both want to build the same Cake object (the specific CakeBuilder will have common methods to build its parts), but both Directors will have different steps how they want to build it (one would want to have double chocolate layer the other double cream layer etc...).Clunk
@TomasBilka If you're making the same object via different means, would an Abstract Factory be a better choice?Mcarthur
@Mcarthur Yes and no. The builder is supposed to deal with complicated objects that are being "build" using common build process. Factory can build anything, but will not address the abstraction of common build phases for similar objects.Clunk
@TomasBilka I understood builder for optional additions, like a query builder in popular ORMs for example. Abstract factory just defines an common interface that factories must adhere to when building their objects. I assumed (maybe wrongly) that these cakes do not have to have each of the given layers, hence builder would allow optional layers to be added.Mcarthur
E
7

The Director does not construct the object, the Builder does, and it's called the Product. The Director is there for one reason: so that the users of the class don't know anything about the steps required to construct the object. All this talk about just flattening it all into one method is like asking why can't we make a car into a unicycle. We could but a. it wouldn't be a car anymore, and b. it wouldn't be able to do all the things cars do that unicycles can't.

One of the best ways to look at Builder is as a fusion of Template Method and a Factory: we need an abstract construction process so we can support the creation of different Products, but the construction process involves many steps. The idea is that once you have the Director/Builder architecture in place, you can add new Builders easily by providing a new concrete implementation. It's like Template Method because the Builder can likewise ignore the details of the construction semantics, and just supply implementations of each required part of the construction (note also that some logic could end up in the abstract base of the Builder hierarchy, further expanding the amount of automatic functionality that the later extenders get for free).

Enrol answered 9/3, 2013 at 23:41 Comment(4)
Thanks for the reply. Does the Builder pattern supposed to have multiple Directors? or is it just one per use-case.Boney
One. The Director is exposing the one liner you seek. The Builders themselves provide implementations for the part logic.Enrol
thanks for the reply. If there's only one Director, i.e only one fixed step-by-step procedure to create parts and construct the object, I don't see the difference between this and the template pattern except the additional layer (Director), for which I don't see the benefit. I tried searching for Builder vs Template method, but they were not satisfactory. I hope you understand my point, and I apologize for extended conversation..Boney
Dude, Template Method is not a creational pattern, so it's not an option here. The Director is useful. You are not forced to have a director. But you are still not getting it. The Director is the one who knows what the construction sequence is. The Builder does not. How can you say that's superfluous?Enrol
N
5

I think you have misunderstood the Builder Pattern. You are saying that the process of building the different components could be merged into one single method, and that's true, but is not the key of this object creation design pattern. Look at this code again:

class Waiter {
    private PizzaBuilder pizzaBuilder;

    public void setPizzaBuilder(PizzaBuilder pb) { pizzaBuilder = pb; }
    public Pizza getPizza() { return pizzaBuilder.getPizza(); }

    public void constructPizza() {
        pizzaBuilder.createNewPizzaProduct();
        pizzaBuilder.buildDough();
        pizzaBuilder.buildSauce();
        pizzaBuilder.buildTopping();
    }
}

Notice that the Waiter works only with a PizzaBuilder, he doesn't know if it's a SpicyPizzaBuilder or a HawaiianPizzaBuilder and that's the goal of this pattern. In this other piece of code:

class BuilderExample {
    public static void main(String[] args) {
        Waiter waiter = new Waiter();
        PizzaBuilder hawaiianPizzaBuilder = new HawaiianPizzaBuilder();
        PizzaBuilder spicyPizzaBuilder = new SpicyPizzaBuilder();

        waiter.setPizzaBuilder( hawaiianPizzaBuilder );
        waiter.constructPizza();

        Pizza pizza = waiter.getPizza();

        waiter.setPizzaBuilder( spicyPizzaBuilder );
        waiter.constructPizza();

        Pizza anotherPizza = waiter.getPizza();
    }
}

you can actually see how this works. A Waiter is created and passed first a HawaiianPizzaBuilder and then a SpicyPizzaBuilder, and with the same instance of Waiter you can construct a pizza and ask for it and he'll deliver the correct one. Hope I've explained myself and that this comment helps you ;) Good luck!!!

Numbersnumbfish answered 9/3, 2013 at 6:11 Comment(3)
Hi, Thanks a lot for the reply. The thing I still don't understand is that, we can't we let the Waiter invoke "only" ConcretePizzaBuilder.createNewPizzaProduct() and let that method take care of step-by-step component creation and whole object construction??Boney
@phani, I see what you mean, and you are right, it's just another way to do it. You could go with a simple constructor like public Pizza(String dough, String sauce, String topping) { ... }, but still, that has nothing to do with the builder pattern, which is in other words: "Hey, waiter make me a hawaiian pizza, and then a metropolitan pizza, but don't tell me how, I don't need to know." Jajaja :D. Hope this comment helps you better understand.Numbersnumbfish
The Waiter should in fact be a Cook. As far as I know waiters just brings the finished meal to the table, they don't cook (construct) them.Clunk
F
2

My explanation of the Builder Pattern: let us assume that we have an Object (Product) and that object construction requires many parameters or components (other objects), now to make things even worse not all of those parameters might be required so this will lead us to either create many constructors with different parameters or introduce many logic statements inside the only constructor to choose this and reject that object and to make this even worse it is possible that those components need to be built in order (in a specific sequence) or do some business rule checking on them, what all this boils down to is a complex constructor that is tightly coupled to the parameters (components) and hard to maintain. The solution is to move this logic into a concrete builder so we get our object by calling ConcreteBuilder.BuildComponent1(), ConcreteBuilder.BuildComponent2(), ..., ConcreteBuilder.GetMeMyObject() but this will tightly couple the client code to the construction process, each client is now fully aware of all the steps required to construct our beloved object, so any change in the construction process will force us to modify all of the client code here and there, to solve this the Builder pattern introduces the Director which encapsulates these steps and now all clients call the Build() method on the Director to build the object. To sum this up, the Director is there so client code doesn't know or get tightly coupled to the steps required to create our beloved object, now why are those BuildComponent1(), BuildComponent2() methods are there for, well they are there to solve the problems the builder pattern is there for and which i mentioned at the beginning: We can now enforce order on the component construction process, we can also enforce business logic that is unique to each concrete builder inside those methods, we can even choose to leave the implementation empty for certain concrete builders because simply our final object (Product) doesn't need that component and we have now encapsulated this complex construction process away from our beloved object who does his work best without worrying on how to construct it self.

Fishery answered 9/3, 2013 at 23:30 Comment(4)
Thanks for the reply. Please could you elaborate: "Because we want to customize each part creation process." Did you mean that selection of components that make up the end product is customizable? i.e. in case of Pizza we may call addSauce() or not, Builder provides it, but it is up to the ConcreteDirector..Boney
@phani, Your correct in part, the end Product is customizable but not because we will call one method and not call another but because each method composes a different part of the end Product so we are actually forcing the concrete Builders to provide their own unique custom parts of the end product, in your example, different kind of pizzas with different sauces and toppings.Fishery
Thanks for the reply. But what I understand from the sequence diagram of the Builder pattern is that the Client creates a Director and configures that with "one" ConcreteBuilder, so it looks like getting parts from multiple builders and makING it into one object is NOT a use-case of Builder pattern. I apologize if i'm extending the topic and testing your patience..Boney
@phani, you're welcome don't worry, you're correct that we are not going to be mixing Builders together. i have modified my answer completely to answer your latest remarks and thoughts and if you still find the need to ask, please don't hesitate.Fishery

© 2022 - 2024 — McMap. All rights reserved.