Timeline for answer to When would you use the Builder Pattern? by user2628
Current License: CC BY-SA 3.0
Post Revisions
43 events
| when toggle format | what | by | license | comment | |
|---|---|---|---|---|---|
| Jul 18, 2024 at 4:14 | comment | added | halt9k | Really want to just fill a structure instead and pass it to constructor in these examples. Probably lifetime of raw constructor args is a necessary complication which is expected to not allow to simply collect them. | |
| Sep 12, 2023 at 19:56 | comment | added | some_groceries | to actually answer the question "what are some real world examples" instead of discussing what builder pattern is; it would be things like: email template builder with attachments, report builder, constructing URL strings, route builder, query builder, middleware pattern. we would use builder pattern in any scenario where creating objects is expensive. ie. the data held by the object might be queried from a database, or requested through http, or calculated with a long running CPU process, or from dependencies. in any such 'lazy' initializations of objects builder pattern would be helpful | |
| Jun 25, 2023 at 2:33 | comment | added | aoeu256 | Why not use these patterns over builder: makePizza $ {size: 12, toppings: [Pepperoni, Cheese, Bacon]}, makePizza({size: 12, fields: ['pepperoni', 'cheese', 'bacon']}), (make-pizza :size 12 :fields '(pepperoni cheese 'bacon)) | |
| Sep 6, 2020 at 23:01 | comment | added | Aubergine | @BarışAkkurt yes you are. After you .build() your pizza you can no longer change it, you can recreate it from scratch but that's it. Until you fully built your object you cannot use it and that's the point, with setters you can start using partly created-inconsistent object immediately, now imagine calling all setters of single class in 20 other different classes - good luck, with builder you can't. My team is also obsessed with builders trying to achieve immutability through this everywhere, I can only say that Kotlin with default parameters + val's is to the rescue. | |
| Mar 9, 2020 at 9:24 | review | Suggested edits | |||
| Mar 9, 2020 at 10:13 | |||||
| Dec 30, 2019 at 0:40 | comment | added | nabster | @Aaron I am confused about "The problem here is that because the object is created over several calls it may be in an inconsistent state partway through its construction. This also requires a lot of extra effort to ensure thread safety." If one thread is creating one object in one method stack then how thread safety becomes a concern here? | |
| Mar 6, 2019 at 9:51 | comment | added | Barış Akkurt | "The problem here is that because the object is created over several calls it may be in an inconsistent state partway through its construction." i did not understand how this problem is solved in the example. If i skip pizza.setCheese(true); call in the JavaBean pattern, I can skip it Pizza pizza = new Pizza.Builder(12).build(); in the builder pattern too and will get the same inconsistent behavior. Am i missing something? | |
| May 28, 2018 at 14:30 | comment | added | Filou |
@Aaron: In order to rely on an immutable object and/or an object that is properly constructed and valid according to your business rules you should declare class Pizza final. Otherwise someone could subclass Pizza and create an instance of it which is mutable and has invalid state.
|
|
| Jan 30, 2018 at 5:39 | comment | added | drum | @Aaron Someone copy and pasted your answer as a blog post medium.com/@modestofiguereo/… | |
| Jul 5, 2017 at 6:16 | comment | added | Govinda Sakhare |
@Aaron I havea doubt, as you said setter approach will leade to "The problem here is that because the object is created over several calls it may be in an inconsistent state partway through its construction". But same could be said about Builder pattern, if we forget to call the builder's data access method for eg. if we forget to call .pepperoni(true) the object will be in inconsistent state.
|
|
| Mar 17, 2017 at 22:10 | comment | added | Andrew Norman | the GOF builder pattern and the Bloch Builder pattern are completely different and non-related design patterns. This post is discussing the Bloch pattern and not the GOF one. | |
| Jun 26, 2016 at 7:44 | comment | added | Tomasz Mularczyk | in example presented by GOF there is a director class which takes Builders with common interface to create object representation while specific elements which are used to create this object are encapsulated. So the same process of construction can lead to diffrent object representations. These are adventages that example above doesn't provide. They only mention about class being director and product. | |
| Jan 10, 2016 at 14:01 | comment | added | BornToCode | You write "The problem here is that because the object is created over several calls it may be in an inconsistent state partway through its construction" - could you please explain or give example to that inconsistent state? (except for when your program is multi-threaded) | |
| Oct 14, 2015 at 9:58 | comment | added | Kaiserludi | @egallardo: So you are telling me that you do not rebuild your oven for every pizza that you bake? ;-) Yeah, in that case you are right, of course. | |
| Oct 13, 2015 at 23:17 | comment | added | egallardo | @Kaiserludi I was specifically talking about runtime changes. Let's try an example for clarity: suppose a jsp page sends a list of ingredients (cheese tomato and basil). Your code would look like Pizza.Builder(12).cheese().tomato().basil().build(). Now, if you only like cheese your code would look like Pizza.Builder(12).cheese().build(); That would be a cumbersome way to build pizzas because you'd need to recompile your code for every order ;-) | |
| Aug 31, 2015 at 14:32 | comment | added | Kaiserludi | @egallardo You miss the point of the whole pattern when you write something like Pizza.Builder(12).cheese(true).pepperoni(false).bacon(false).build(); A key advantage of this pattern is, that you don't have to pass in default values for optional parameters, but can just leave them out completely, no matter the parameter order. So you could instead simply write Pizza.Builder(12).cheese(true).build(); However: Who in their right mind would order a pizza with just cheese and nothing else? ;-) | |
| Aug 25, 2015 at 5:27 | comment | added | Robert Harvey | @insidesin: If only there were a way to write a constructor with optional arguments... | |
| Aug 25, 2015 at 5:13 | comment | added | Robert Harvey | @doctordoder: My point is that the builder and the fluent interface are two different concepts. Yes, you can use them together, but the similarity pretty much ends there. | |
| Aug 25, 2015 at 5:04 | comment | added | michaelsnowden | @RobertHarvey Yeah, exactly. So I don't see why you say this is "more like" a fluent interface than a builder. Most builders are coded like this. | |
| Aug 25, 2015 at 4:42 | comment | added | Robert Harvey |
@doctordoder: You can have a builder that's not fluent. A fluent builder requires that the setter methods return this. You can also have fluent methods that are not builders; see Linq for an example.
|
|
| Aug 25, 2015 at 3:24 | comment | added | michaelsnowden | @RobertHarvey How is this more like a fluent interface than a builder? This is a textbook builder class, and they're different things: stackoverflow.com/a/17940086/2770572 | |
| Mar 17, 2015 at 13:00 | comment | added | Dmitry Trifonov | The telescoping constructor anti-pattern occurs when the increase of object constructor parameter combination leads to an exponential list of constructors. | |
| Mar 1, 2015 at 9:13 | comment | added | frostymarvelous | @nawfal I think the main problem is like with most programming questions. The answer oversimplifies the problem in order to help the OP understand. IMO, that is the main cause of the proverbial hammer. | |
| Mar 1, 2015 at 5:25 | comment | added | nawfal | @frostymarvelous in which case builder pattern is fine and worth it... | |
| Feb 24, 2015 at 6:55 | comment | added | frostymarvelous | @nawfal you're assuming your builders will be for your own classes. What if you needed to wrap some other class? Do something based on the parameters like instantiate new objects for building? I have to agree that I would rather use the javabean pattern in my own work but both do have their place. | |
| Apr 19, 2014 at 13:03 | comment | added | Maarten Bodewes | @JasonC Right, and what use is an immutable pizza anyway? | |
| Jan 15, 2014 at 22:28 | comment | added | Raman Zhylich | This implementation has neither Director nor ConcreteBuilder classes. It doesn't follow Builder pattern. | |
| Nov 21, 2013 at 22:59 | comment | added | egallardo |
@Fabian Steeg, I think people are overreacting to to the nicer looking boolean setters, keep in mind that these kind of setters don't allow runtime changes: Pizza.Builder(12).cheese().pepperoni().bacon().build();, you would need to recompile your code or have unnecessary logic if you only need some pepperoni pizzas. At the very least you should also provide parametrized versions like @Kamikaze Mercenary originally suggested. Pizza.Builder(12).cheese(true).pepperoni(false).bacon(false).build();. Then again, we never unit-test, do we?
|
|
| Sep 11, 2013 at 16:41 | comment | added | SonOfPirate | @SACO, I can tell you the reason I use the pattern is to construct objects that do not have public setters. I can maintain better governance on my domain model this way. The builder is responsible for making sure I can only create valid variants of my domain object while methods on that object allow consumers to change its state. These methods can provide whatever guards are required and encapsulate all of the logic and state changes required to perform the required operation. If left to the consumer to set a new value for each property, etc. errors/violations will occur. | |
| Aug 9, 2013 at 14:18 | comment | added | Daniel Bişar | I still don't understand why you should use this. In the case above you could just use a class which contains the parameters you need to set (to gain the readability) and pass this parameter to a factory which will create the actual pizza. | |
| Jun 11, 2013 at 12:39 | history | edited | usr-local-ΕΨΗΕΛΩΝ | CC BY-SA 3.0 |
Enhanced indentation for readability
|
| Apr 18, 2013 at 16:40 | comment | added | nawfal | honestly, I find builder pattern more work for little gain compared to javabean pattern | |
| Feb 1, 2013 at 22:08 | comment | added | Adam Parkin | @BuhakeSindi I suppose, but it's at the very least a simplified version of the GoF builder. For example, the GoF pattern as outlined in the book allows for the potential of building completely different products by simply replacing the builder within the client thereby reusing the director. It seems to me that in the Bloch Builder you'd have to duplicate the "director" in a new product. | |
| Nov 28, 2012 at 22:23 | comment | added | Robert Harvey | This looks more like a Fluent Interface than a builder pattern. | |
| S Oct 4, 2012 at 9:14 | history | suggested | reevesy | CC BY-SA 3.0 |
linked to effective java and turned blod text into a quote as it is a quote from the book...
|
| Oct 4, 2012 at 9:12 | review | Suggested edits | |||
| S Oct 4, 2012 at 9:14 | |||||
| Feb 20, 2012 at 18:35 | review | Suggested edits | |||
| Feb 20, 2012 at 19:11 | |||||
| Sep 21, 2011 at 11:58 | comment | added | Buhake Sindi |
@Lino Rosa, it is still a GOF builder pattern, the Pizza is the director. :-)
|
|
| Dec 24, 2009 at 16:30 | comment | added | user2628 | @Lino It actually is a form of the GOF Builder. | |
| Dec 24, 2009 at 1:05 | comment | added | user2628 | Sure - I just used the boolean values for the sake of example. In reality you would most likely be using a builder for more complex parameters. | |
| Dec 24, 2009 at 1:03 | comment | added | Fabian Steeg |
For this particular example, wouldn't it be nicer to remove the boolean parameters and be able to say new Pizza.Builder(12).cheese().pepperoni().bacon().build();
|
|
| Dec 24, 2009 at 0:02 | comment | added | Lino Rosa | Different from the original GOF builder right? Because there is no Director Class. Seems almost like another pattern to me, but I agree it`s very useful. | |
| Dec 23, 2009 at 15:52 | history | answered | user2628 | CC BY-SA 2.5 |