I've seen this question rise here and there a few times, but I never found and answer I was happy with.
From Wikipedia:
Builder focuses on constructing a complex object step by step. Abstract Factory emphasizes a family of product objects (either simple or complex). Builder returns the product as a final step, but as far as the Abstract Factory is concerned, the product gets returned immediately.
But to the client isn't it the same thing? He gets the full object once it's built, so to him there is no added functionality.
The only way I see it is as a way or organizing the constructor code in steps, to force a structure for the implementation of the builders. Which is nice, but hardly a great step from the abstract factory.
This next bit from Wikipedia is a good reference to get to my point:
Often, designs start out using Factory Method (less complicated, more customizable, subclasses proliferate) and evolve toward Abstract Factory, Prototype, or Builder (more flexible, more complex) as the designer discovers where more flexibility is needed.
If that's so, what kind of complexity would have to be introduced in your system where you would cha开发者_Go百科nge from a Abstract Factory to a Builder?
My point is that I can't find and example where it's clear that an Abstract Factory won't suffice and you would need a Builder instead.
The AbstractFactory is for a family of related products. The Builder is for one product.
The Builder is for building a complex product step by step, while the AbstractFactory is to build in an abstract way (that is, once for several implementations) a less complex product.
Examples of what the difference means to the calling code:
To the client code using an AbstractFactory, each method call builds one object. The client has to assemble them together. On the other side, a builder would assemble them internally, and deliver the full object graph as the last step of the building.
The builder allow to pass and check parameters one by one for the client code. But he may build the final product in one step (for example, a call to a constructor, passing in all parameters at once, even sophisticated ones that have been build themselves). So the product of a builder could be an immutable object (or graph of) (which is priceless in multi-threaded environment, for performance and memory reasons).
UPDATED in response to this comment :
Lino > It's still bothering me, though :). I mean, if you are building composite objects, and you take the director out, passing the responsibility of calling the builder methods to the clients, then it works for me. Only then the builder would seem a perfect fit. But with the director, it doens't seem like much...
Precisely, the Builder has no director, it lets each client create a complex product according to it's specific needs. The client is the director, because the director's implementation is not reused.
If you need to reuse a few times a complex building process, then you can have a method to encapsulate this (and this method is your "director").
On the contrary, for the AbstractFactory, you typically need a reusable Director, that create products alike (provided with a Factory implementation).
Some very good answers here already. I'm just offering an analogy.
Say you wanted a new desk for your new office. You go to a 'factory' and see selections then pick one of the shelf. If it fits your needs, great!
Now you have a larger office with really fancy shaped walls. Now you need a desk with the top shaped to fit your office. And you want a different legs to suit the rest of the furniture and also to fit your new Aeron chair.
You go back to the same factory, no luck. You go to a carpenter who can custom 'build' what you want. You give your specs and requirements and the 'builder' will tell you certain limitations. After a few iteration, you got the perfect desk!
Ok, a lame story but just to lighten things up :P
One good example where you'd want a builder is if you were building something piece by piece based on command line arguments. For example, consider a builder with methods like...
setName()
setType()
setOption()
A builder could also be combined with an abstract factory where the director asks the factory for a concrete product. Again, this could be done with just a factory pattern by passing the args list to the factory but what if the args were instead messages coming from a server or a client.
Sometimes the aesthetics of one pattern just fit nicer than the aesthetics of the other.
Builder is useful for configuration. Abstract Factory is useful when you don't want callers to care about the actual implementation. Two different purposes.
You could, in fact, mix the two patterns. For example Java's DocumentBuilderFactory is a classic abstract factory: if you read the docs, you'll see the process that it uses to pick an implementation. However, the DocumentBuilders that it produces can be configured afterward (although they don't follow the prototypical "builder" approach of having each configuration method return the object being configured).
Builder is an inversion of control, like the Template Method Pattern. The various functions on your concrete builder are customizable steps in a process. Abstract Factory is "just" polymorphism, where the output happens to be a newly-constructed object. The various functions on a concrete factory are different customizable processes, each presumably resulting in a different object.
So, you need a builder when you need there to be a common overall "plot" for constructing your objects, but with individual "scenes" within that plot being different. You need a factory when there is not necessarily anything at all in common between different implementations.
I think you could conceivably use both at once, with the Abstract Factory acting as the director in the Builder pattern, and each concrete factory directing things differently. However, that goes beyond the "napkin" limit for UML diagrams ;-)
I use an Abstract Factory when I will need to build multiple child factories to create different types of objects. These child factories all implement or extend the Abstract Factory. I use a Builder when there's only one type of object that needs to be built.
I'm not sure if this is the correct usage, but it is how I've seen it done, and how I've done it in the past.
Let's consider an analogy.
You're at a Fast Food chain, where the fast food you actually get is quite complex. Not only is it complex, but only certain people can take your order for certain types of food. Now, you don't know that, because the manager of the store decided to put one person behind one cash register. But if you look at him carefully, it's actually an advanced hologram because it's "abstract". An abstract order taker. Now, when you talk to the hologram, and place your order, the hologram computer reroutes (polymorphism) that order to an implant in the brain of a human order taker. The implant makes the human actually punch in the order to a real register. There are few of these "concrete" mind-controlled human beings being ordered about by the hologram. Now, when the real human being punches in the order, it get's sent to a computer in the back where there's an assembly line, or a "builder", for each type of food being built. Orders are sent to different kinds of assembly lines based on the human being and his cash register.
So, the hologram is the abstract factory, the mind-controlled humans at the registers are the concrete factories, and the assembly lines are the builders. This is a way you can actually visualize the flow of an abstract factory working WITH the builder pattern. Sometimes it's best to see how design patterns work together in order to see how they're different.
If you're looking for extra credit, try implementing this with generics. It doesn't require as much code as you might think.
For more information on when to use the Builder Pattern and its advantages you should check out my post for another similar question here
In practice, you'll probably use DI + IOC in order to do what a builder used to do. FYI.
Good answers, would like to add mine in the hopes I discover that my understanding is correct.
If you have a new office, and only need new desks, you would use a Builder. A desk will always be a desk, but there are many different configurations for a desk, i.e., size, shape, presence of a hutch, drawers, etc.
If you have a new office, and the inside is completely bare, you would need various objects and would use an Abstract Factory that creates Furniture, from which our Desk descends. In this case, Desk as we know is a "complex" object, so it uses the Builder pattern, but here it is part of a directing Abstract Factory. The Abstract Factory would also create simple objects, like very specific lamps (StraightFunkyLamp), via a StraightFunkyLampFactory class.
精彩评论