“Separate the construction of a complex object from its representation so that the same construction process can create different representations.”
Design Patterns: Elements of Reusable Object-Oriented Software
Just like the Abstract Factory pattern, Builder is also a creational pattern, with the same goal: create another (in this case, more complex) objects. To stick with the previous data access example, imagine that you have a class with many properties to set, for example, a DbCommand derivate: SqlCommand. You can build SqlCommand objects with the SqlCommandBuilder class, a derivate of DbCommandBuilder. Now SqlCommandBuilder is very intelligent, it builds a complete command object from just a SqlDataAdapter object (which has everything that a command should need: a connection object and a select command object).
The key participants of the process:
- Builder: the abstract base builder class, in our case, DbCommandBuilder.
- ConcreteBuilder: the concrete implementation of our abstract base builder class, with the key operations overridden.
- Product: in this case, it’s a SqlCommand object. Note that there is no abstract product base class, because the different builders’ different products may have very little in common.
Because we have no abstract product class/interface, we should create our abstract builder class to be very flexible, with a set of virtual methods to be overridden.
I haven’t said anything about the construction process so far. You must understand the key difference between builder and other creational patterns. Builder creates objects in a step-by-step manner, not in a one-shot style, like abstract factory. That means you build your objects by calling a set of methods, instead of just passing everything into a constructor, etc. Given this, you get a good isolation of the creational code and the representation.
A quick example:
SqlCommandBuilder theBuilder = new SqlCommandBuilder();
theBuilder.DataAdapter = new SqlDataAdapter(sqlConnection, sqlCommand);
theBuilder.ConflictOption = ConflictOption.OverwriteChanges;
SqlCommand delCommand = theBuilder.GetDeleteCommand();
As you can see, with a set of properties, we were able to create a DeleteCommand object without even knowing what it is. But we could have also created an insert or update command as well, the Builder pattern let us do just that.
Design Patterns(book): pp 97-106