Building an object
I came across a rather unusual way to build an object of a class in this blog : http://marchwicki.pl/blog/2010/11/building-a-pojo-in-an-elegant-way/. Is thi开发者_StackOverflow社区s a good way to do this. What are the benefits?
I came across a rather unusual way to build an object of a class in this blog : http://marchwicki.pl/blog/2010/11/building-a-pojo-in-an-elegant-way/.
This is the builder design pattern with a fluent interface.
As you see from the article, the two ideas are complementary and often used together (which I've seen some call a "fluent builder"), so much so, that they are often confused as the same thing:
The builder pattern abstracts and simplifies the construction of a complex object into simpler steps.
The builder pattern is discussed in the "Gang of Four"'s Design Patterns book
Joshua Bloch talks about builders as Item 2 in his book Effective Java
A fluent interface is an API-style that uses contexts and method chaining to improve the readability of code.
- See Martin Fowler's post about fluent interfaces:
http://www.martinfowler.com/bliki/FluentInterface.html
- See Martin Fowler's post about fluent interfaces:
Note that you can use the builder pattern without a fluent interface (e.g. a builder with simple setters). You can also use the fluent interface idea in more contexts than just builders (e.g. to improve the readability of a set of overloaded methods with many parameters and parameter variations).
Is this a good way to do this?
This "fluent builder" seems highly accepted as "a good way to do this" (at least based on the number of articles and blog posts I've seen proselytizing the idea).
What are the benefits?
Each idea has its own distinct advantages/benefits. For example, see:
Builder - When would you use the Builder Pattern?
Fluent Interface - What's a fluent interface?
The only benefit is readability. By the way, this is an example of a fluent interface.
A fluent interface seeks to provide an API that, when used, produces more readable code than a standard OOP API tends to provide.
Yes, this is what Joshua Bloch had in mind in Chapter 2 of his "Effective Java".
This is a simple example of the Builder pattern. It allows the separation of the algorithm for creating a complex object from the parts that make up the object and the way they are assembled. GoF explains the consequences of this pattern as:
- It lets you vary a product's internal representation. The Builder object provides an abstract interface for constructing the product. The interface lets the builder hide the representation and internal structure of the product. It also hides how the product gets assembled. Because the product is constructed through an abstract interface, all you have to do to change the product's internal representation is define a new kind of builder.
- It isolates code for construction and representation. The Builder pattern improves modularity by encapsulating the way a complex object is constructed and represented. Clients needn't know anything about the classes that define the product's internal structure; such classes don't appear in Builder's interface. Each ConcreteBuilder contains all the code to create and assemble a particular kind of product. The code is written once; then different clients can reuse it to build Product variants from the same set of parts.
- It gives you finer control over the construction process. Unlike creational patterns that construct products in one shot, the Builder pattern constructs the product step by step under the control of the user of the builder object. Only when the product is finished does the user retrieve it from the builder. Hence the Builder interface reflects the process of constructing the product more than other creational patterns. This gives you finer control over the construction process and consequently the internal structure of the resulting product.
A real-world example of this pattern is the ProgramNodeBuilder
class in the Smalltalk-80 compiler sub-system. Source code is parsed by an object of the Parser
class which is initialized with a ProgramNodeBuilder
. The Parser
object notifies its ProgramNodeBuilder
object each time it recognizes a syntactic construct. When the parser is done, it asks the builder for the parse tree it built and returns it to the client.
I'm quite happy to do my first stackoverflow post here - cause you are discussing my article :-)
I think this construction (leverage of both builder and fluent interface: fluent builder) greatly improves code readability. What is more (and not getting into discussion around design patterns) it proves its value when we need immutable objects. Simply, by making constructor private and removing all the setters, we gain a very powerful tool for an elegant and readable, yet powerful way of building immutable objects. Finally, the whole post was supposed to be more about smart usage of templates to generate repeatable code - but I pretty like the discussion.
I personally find using a Builder with a Fluent Interface very useful and very intuitive. You can express better your intents when sending messages to the builder.
I wrote a little example of a Builder with Fluent Interface, hope it helps.
http://jpereira.eu/2011/10/12/fluent-interfaces-while-trying-to-make-sense-of-prototype-pattern/
精彩评论