Created
October 15, 2015 13:51
-
-
Save daniellowtw/275156a13f56aa034559 to your computer and use it in GitHub Desktop.
An exploration of the cake pattern for scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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