此article通过Scala的Cake Pattern
解释依赖注入。
我对这种模式的好处的理解是,特征可以与(生产对象)和静态检查混合在一起。
在Bonér先生的例子中,他列出了这个完成的(每个例子)代码:
UserRepositoryComponent 和 UserServiceComponent
我根据我的理解添加了评论。
trait UserRepositoryComponent {
val userRepository: UserRepository // stand-alone component
class UserRepository {
... // actual implementation here
}
}
trait UserServiceComponent {
this: UserRepositoryComponent => //Requires a mixed-in UserRepo*Component
val userService: UserService
class UserService {
... // actual implementation here
}
}
我的理解是Service
取决于注入Repository
组件。
出于生产目的,可以使用以下内容将“生产”Repository
组件连接到UserServiceComponent
:
object ComponentRegistry extends
UserServiceComponent with
UserRepositoryComponent
{
val userRepository = new UserRepository
val userService = new UserService
}
如果我们的生产代码想要使用userRepository
或userService
,通过简单import
使用它们的正确方法是什么?
我认为到目前为止我理解了文章的一半,但我不确定如何使用ComponentRegistry
对象。
答案 0 :(得分:7)
你首先进入厄运兄弟的面包店: What are some compelling use cases for dependent method types?
要回答您的问题,使用userService
的正确方法是使用其他特性并将其搞砸:
trait Example { this: UserServiceComponent =>
def getExampleUser() = userService.getUser("ExampleUser")
}
现在无论这个新特性做什么都没有直接耦合到对象ComponentRegistry
之类的东西。相反,您的应用程序变为:
object Application extends
Example with
UserServiceComponent with
UserRepositoryComponent
{
val userRepository = new UserRepository
val userService = new UserService
}
无论如何,你应该跑到山上去,因为如果你真的想要用蛋糕,你应该做更像这样的事情:
trait UserRepositoryComponent {
type UserRepository <: UserRepositoryLike
val userRepository: UserRepository
trait UserRepositoryLike {
def getUserOrSomething()
}
}
trait UserRepositoryComponentImpl extends UserRepositoryComponent {
type UserRepository = UserRepositoryImpl
val userRepository = new UserRepositoryImpl
class UserRepositoryImpl extends UserRepositoryLike {
override def getUserOrSomething() = ???
}
}
trait UserServiceComponent {
this: UserRepositoryComponent =>
type UserService <: UserServiceLike
val userService: UserService
trait UserServiceLike {
def getUserNameById(id: Int): String
}
}
trait UserServiceComponentImpl extends UserServiceComponent {
this: UserRepositoryComponent =>
type UserService = UserServiceImpl
val userService = new UserServiceImpl
class UserServiceImpl extends UserServiceLike {
override def getUserNameById(id: Int) = userRepository.getUserOrSomething
}
}
trait Example {
this: UserServiceComponent =>
def getExampleUser() = userService.getUserNameById(1)
}
object Application extends
Example with
UserRepositoryComponentImpl with
UserServiceComponentImpl
现在节省一些时间,放下蛋糕模式,然后做一些simple。