阅读这篇博文后,我开始使用蛋糕模式:https ://github.com/precog/staticsite/blob/master/contents/blog/Existential-Types-FTW/index.md 方法与大多数蛋糕模式不同使用存在类型而不是自我类型的帖子。
我已经使用这种模式几个月了,它似乎工作得很好,因为我可以在我想要的时候指定一个模拟。它确实有更多的依赖注入感觉,但它具有将代码放入特征中所获得的所有好处。
我使用存在类型的问题的混蛋版本将是这样的:
case class Pet(val name: String)
trait ConfigComponent {
type Config
def config: Config
}
trait Vet {
def vaccinate(pet: Pet) = {println ("Vaccinate:" + pet)}
}
trait PetStoreConfig {
val vet: Vet
}
trait PetStore extends ConfigComponent {
type Config <: PetStoreConfig
def sell(pet: Pet) {
config.vet.vaccinate(pet)
// do some other stuff
}
}
您可以将所有内容放在您的应用程序中
class MyApp extends PetStore with PetStoreConfig {
type Config = MyApp
def config = this
val vet = new Vet{}
sell(new Pet("Fido"))
}
scala> new MyApp
Vaccinate:Pet(Fido)
res0: MyApp = MyApp@668dd96c
您可以通过创建 VetLike 的实例并创建 VetLike 的模拟来单独测试组件,并使用它进行 PetStore 测试。
//Test VetLike Behavior
scala> val vet = new Vet{}
scala> vet.vaccinate(new Pet("Fido"))
Vaccinate:Pet(Fido)
//Test Petstore Behavior
class VetMock extends Vet {
override def vaccinate(pet: Pet) = println("MOCKED")
}
class PetStoreTest extends PetStore with PetStoreConfig {
type Config = PetStoreTest
def config = this
val vet = new VetMock
val fido = new Pet("Fido")
sell(fido)
}
scala> new PetStoreTest
MOCKED