What is the difference between a fluent interface and the Builder pattern?
The idea behind a Fluent interface is that one can apply multiple properties to an object by connecting them with dots, without having to respecify the object each time. The idea behind the builder pattern is that unshared mutable objects are often easier to work with than unshared immutable ones, but it's much easier to reason about shared immutable objects than shared mutable ones. Thus, code can use an an easy-to-work-with mutable object to produce a "model" of a desired instance, and then use that to make an easy-to-share immutable object that holds the same data.
The two ideas can work well together, but are somewhat orthogonal.
Note that there are at least three ways a fluent interface can work:
- By having each member of an instance return a new instance with the appropriate change applied.
- By having each member mutate the instance upon which it is invoked and return that.
- By having each member return an instance of a lightweight patch object which holds a link to either the thing being modified or the previous patch.
The last style requires that some action be taken to apply all the patches, but if the object being modified is large and many changes are necessary, it can minimize the amount of copying that's required.
Fluent Interfaces are semantic facades. You put them on top of existing code to reduce syntactical noise and to more clearly express what the code does in an ubiquitous language. It's a pattern used when building an internal Domain Specific Language. It's about readability.
A director/builder orchestrates the building of something. That is, if you are building a Pizza baking machine, the Director would make sure that the steps from order to pizza are executed in the right order with the right data by the right builder. It's about validation and delegation.
You can certainly put a Fluent Interface on top of a Director/Builder pattern to make it read more - well - fluently and to emphasize the domain concepts (vs. the technical process of building and delegating). That would probably be an Expression Builder then.
I'd like to stress that Fluent Interfaces are not just Method Chaining. It's a common misconception. Method Chaining is one approach to implement a Fluent Interface but it's not the same, because it lacks the semantic qualities, e.g. this is not a Fluent Interface:
SomeObject.setFoo(1).setBar(2).setBaz(3);
The above does not express anything about SomeObject. It's not a facade on top of some semantic model. It's just some methods chained. An example of a Fluent Interface would be a SQL query builder, e.g.
SQLBuilder.select('foo').from('bar').where('foo = ?', 42).prepare();
Under the hood of that API lies the code to create an SQL statement. It might include several objects and the calls shown could very well create a Select object, call a setter on it, create a Condition object and apply it to the Select object and finally return a Statement object. But all that is hidden from us. This also highlights another aspect of Fluent Interfaces: they might violate SOLID and Law of Demeter. But since it's a facade on top of code that hopefully follows these design principles, it doesn't matter that much, because you localize the violations to the Fluent Interface.