Cake Pattern, Self Types and Realistic Example
09 April 2014 Comments off
Reading time:
2 minutes
Word count:
407
Original drafted 17 March 2014 for an incomplete article.
The Cake pattern for Scala using a flaming cake as well.
This is the quasi-production code:
package uk.co.xenonique.learning.cake /** * The type Cake * * @author Peter Pilgrim */ class Cake(val name: String) { def inspect(): String = { name } } trait Oven { def powerUp(): Unit def powerDown(): Unit } trait CakeMaker { def bake( cake: Cake ) } trait CakeFactory { def produce( cakes: List[Cake] ) } class CakeFactoryImpl extends CakeFactory { this: CakeMaker with Oven => override def produce( cakes: List[Cake] ): Unit = { powerUp() for ( c <- cakes) { bake(c) } powerDown() } }
This is the learning test code:
package uk.co.xenonique.learning.cake import org.scalatest.WordSpec import org.scalatest.matchers.MustMatchers import org.scalatest.mock.MockitoSugar /** * The type CakeSpec * * @author Peter Pilgrim */ class CakeSpec extends WordSpec with MockitoSugar with MustMatchers { trait Baker extends CakeMaker { override def bake(cake: Cake): Unit = { println(s"I'm a baker, baking a cake: "+cake.inspect()) } } trait IndustrialOven extends Oven { override def powerUp() = { println("firing up the oven") } override def powerDown() = { println("venting the oven") } } "Cake" should { "understand the cake pattern" in { val factory = new CakeFactoryImpl() with Baker with IndustrialOven { } val cakes = List( new Cake("Battenburg"), new Cake("Cherry Madeira"), new Cake("Lemon and Lime")) factory.produce(cakes) } } }
Assuming that you know what you are doing: insert this code into a test Scala project with a decent IDE. Run the test should demonstrate the results.
What is the benefit of this so-called Cake Pattern? Well in short, Scala allows self-type with multiple traits (the dependencies). See the definition of CakeFactoryImpl
, which expresses a dependency on the type CakeMaker and an Oven traits being mixed-in to the final concrete class. In other words, the final CakeFactoryImpl
is a type of CakeMaker
(Baker
) and also it is type of Oven
(IndustrialOven
). Therefore, it is a small exercise to write mock objects with these traits, hence the reason I demonstrated with the pattern using a ScalaTest. In fact, it is an exercise to the reader, to write Mockito mocks of this CakeFactoryImpl. Imagine if your Oven was a reference, wrapper or connection pool to a database.
Finally, to understand the cake pattern you have to comprehend the Scala self-types and annotations. Personally, I found this pattern a little convoluted, because of the traits tend to have partial implementations in a production work.