The Builder pattern in Scala

July 17, 2011

Throughout my Java travels, I found the builder pattern to be useful in saving me from redundant object instantiation boilerplate, confusing constructor overabundance, and invalid object initialization state. The second pattern in the GoF Design Patterns book and the second item in Josh Bloch's Effective Java, Builder is well-established and oft-used in the world of Java.

Scala's case classes can consist of nothing but a potentially lengthy constructor. More generally, constructor and method signatures can grow with the complexity of the problem domain. This seems vulnerable to the same issues solved in Java by a builder, and indeed this was the case until Scala 2.8. The introduction of named and default arguments in Scala 2.8 largely solve this problem, giving the developer the ability to effectively create many usable constructor and method patterns while only writing them once.

The shell introduced in ScalaTest 1.5 has an interesting way of using Scala case classes to bring back the utility of the builder with a new twist. The Shell case class includes several lazy vals which act as builders to create Shell instances with specific configurations.

case class Shell(private val colorPassed: Boolean = true,
                 private val durationsPassed: Boolean = false,
                 private val shortStacksPassed: Boolean = false,
                 private val fullStacksPassed: Boolean = false,
                 private val statsPassed: Boolean = false) {
  lazy val color: Shell = copy(colorPassed = true)
  lazy val durations: Shell = copy(durationsPassed = true)

See also