This time we’ll talk about the Immutable Builder Pattern, but with a twist: the resulting instance has to be immutable.
From time to time I need to move away from the routine, just to avoid getting bored. Also, taking short breaks might help viewing things under a different perspective. Anyways, while working on Statifier I felt the need to get back to the roots and dive a little bit into the Design Patterns World ™ .
Straight from Wikipedia:
“the intent of the Builder design pattern is to separate the construction of a complex object from its representation”
This pattern is indeed extremely useful when you have to create an instance of a complex class, eg. with a long list of properties that have to be initialized.
It can be confused sometimes with the Factory pattern, but there’s a very important difference: Factories can be used to create an object instance based on some rules and return an interface. The result will be any concrete implementation of that interface, but consumers won’t (and don’t need to ) know which one.
Builders instead know how to create a single, specific class and the result is exactly an instance of that class.
And why should I be using the Builder if it can create just one thing? Well maybe because the creation is complex and requires several steps. Maybe you cannot just do something like builder.Build(param1, param2…..) , but you need a more structured approach.
The Wikipedia page has already some good examples of how the pattern can be implemented so I won’t talk much about that.
But what is immutability anyway? Why do I need it?
At its core, immutability is a simple, very important concept: don’t let anyone from the outside update the internal state of your objects. That’s it.
Coding-wise, it translates basically into classes with no setters at all. All the properties will be initialized in the cTor, along with all the dependencies.
And why should I use it? Here’s an excellent article by Martin Fowler (yeah I love quoting him). Take your time, I’ll wait.
Ok so now let’s get back to out Builder. Here’s a sample implementation:
Few points to note:
- Vehicle cTor is private. Only the Builder can create an instance, and this is the main reason why the Builder class is declare inside the Vehicle class.
- all properties on Vehicle are get-only. Internal state cannot be changed, immutability is ensured. Good luck changing them.
- every call to Build() creates a new instance of Vehicle. This is again made to ensure immutability but comes with a twist: you have to be more careful if you want to reuse an instance of the builder to create more vehicles. You’ve been warned.