Skip to content

Instantly share code, notes, and snippets.

@daniellowtw
Created October 15, 2015 13:51
Show Gist options
  • Save daniellowtw/275156a13f56aa034559 to your computer and use it in GitHub Desktop.
Save daniellowtw/275156a13f56aa034559 to your computer and use it in GitHub Desktop.
An exploration of the cake pattern for scala
import org.scalatest.mock.MockitoSugar
/**
* This explores self type and the cake pattern
*
* The recipe:
* 1) Create a trait component
* 2) Declare any dependent components using self-types
* 3) Create the trait
* 4) Create an abstract val that will be instantiated with an instance of the component
* 5) Optionally provide implementations of the component's interface
*/
class MyCakePattern extends MockitoSugar {
//Wiring
object App extends AComponent with BComponent {
// We declare the necessary components
override protected val a: A = new myA()
// Use the given implementation
override val b: B = new myB()
}
val myActualB = App.b
//Classes
val testApp = new BComponent with AComponent {
//This provides a nice way of injecting dependencies
override protected val a: A = mock[A]
override protected val b: B = new myB()
}
}
// A basic component
trait AComponent {
trait A {
def ourTestString: String
def someRandomUnusedString: String
}
protected val a: A
protected class myA extends A {
override def ourTestString: String = "2"
override def someRandomUnusedString: String = ""
}
}
/**
* 151015
* What about classes with constructors that you want to do dependency injection with?!
* Doing the whole traitComponent, trait wrapper around an injection seems like a lot of overhead
*/
// A component that depends on some other component
trait BComponent {
this: AComponent =>
// requires A component and now can access a!
trait B {
def someNecessaryFunctionThatUsesA: Unit
}
protected val b: B
// Example concrete impl that defines some methods
protected class myB extends B {
override def someNecessaryFunctionThatUsesA: Unit = {
println(a.ourTestString) // We can use a here!
}
def someOtherFunctionThatCanBeOverridden: Unit = {
println("Useless")
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment