Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between Abstract factory and builder?

Sorry for asking again. I have searched over web but couldn't understand hence i have to put here. Here what I research by my self. I studied from head first design pattern.

Abstract factory pattern :

As per the differences i studied that builder some senses it is a Factory, but it only creates one type, most of the time.
So can i say NYStore in above image is builder as it returns pizza object to client? am i correct? Please give your answer on bases of above example which may help me to learn it.

like image 642
Suri Avatar asked Dec 14 '22 21:12

Suri


1 Answers

Interesting. I'd recommend a few changes to the diagram to make it fit the classical Builder pattern as defined by the GoF.

The big difference is that in the builder pattern, the "director" gets to be unaware of the details of the builders. So instead of having a class called NyPizzaStore with a method called createPizza() that (obviously) is highly tuned to creating a NY style pizza, you might instead have a class call PizzaChef that takes in an instance of a class that customizes how the details of how the pizza is made. (For this example/analogy, let's rename renamePizzaIngerdientFactory to Recipe so we can treat it just a bit differently). So that gives you PizzaChef.createPizza(Recipe r). The PizzaChef class does not need to worry if the clams are fresh or frozen, he simply calls each of the builders in turn and creates the desired pizza. This is pivotal to the difference...there is only one PizzaChef and he is unaware of the details (subclasses) of the Recipe.

A nice side effect of this is that you can easily mix-and-match the builders that make up the Recipe class such that you can create a NewHavenStyle pizza by using all the same ingredient builders as the NYStyle, but swap in a BrickFiredThinCrust instead. Much more customizable. Recipe becomes a holder for the builder instances.

And of course, now I'm hungry :)


Be careful that you do not confuse the name of a pattern (which is a reusable technique involving, almost always, multiple objects / participants / roles), and the name of a specific role in a pattern. Additionally, often patterns build on top of each other and have a lot of overlap.

In the Builder pattern, there is a Director object that would have a createSomething() method (not call it). That method would call, in a very formulaic way, the one or more part builders. The client has a reference to the Director, and passes in the builder(s). The client, directly or indirectly, influence what gets built. The Director has no need to be a subclass of anything, it could be a simple, sealed class. PizzaChef is not the client but rather the director. It does not inherit from anything, nor does it get inherited. The client in this case might be something like a Customer class.

Now, just as the Abstract Factory pattern is built upon a set of Factory Methods (from the pattern of that name), you could have a Builder pattern utilize an Abstract Factory . You could pass in the builders to the Director as an AbstractFactory. In that case, the Recipe would be your AbstractFactory, and NyStyleRecipe would subclass Recipe and provide the builder methods that the PizzaChef class would use to create a pizza. In this sepecific implementation, the Directpr of the Builder pattern would indeed be client as described in your original diagram.

But as I tried to allude to before, that is not the only have to implement the Builder pattern, and I think it adds limitations that Builder is designed to overcome. I would use a composeable Recipe class instead because you can then mix-and-match ingredients much more easily. There is not really a connection between thin crust and NY-style pizza. New Haven style uses thin style too.

Recipe newyorkStyle = new Recipe(
   new ThinCrustBuilder(), 
   new RedSauceBuilder(), 
   new FreshClamsBuilder(), 
   new ElectricOvenBuilder());

Recipe newhavenStyle = new Recipe(
   new ThinCrustBuilder(), 
   new WhiteSauceBuilder(), 
   new FreshClamsBuilder(), 
   new BrickOvenBuilder());

PizzaChef chef = new PizzaChef ();

nyPizza = checf.createPizza(newyorkStyle);

nhPizza = checf.createPizza(newhavenStyle);

Note that I used composeable builders to reuse the thin crust and the fresh clams. This would not be as easy with an Abstract Factory

I hope that clarifies the differences a bit more!

like image 62
tcarvin Avatar answered Dec 28 '22 05:12

tcarvin