[英]DI in Scala with Cake Pattern
This article explains Dependency Injection via Scala's Cake Pattern
. 本文通过Scala的
Cake Pattern
解释了依赖注入。
My understanding of this pattern's benefit is that traits can be mixed in (production v. test) with static checking. 我对这种模式的好处的理解是,特征可以与(生产对测试)混合使用静态检查。
In Mr. Bonér's example, he lists this finished (per example) code: 在Bonér先生的例子中,他列出了这个完成的(每个例子)代码:
UserRepositoryComponent and UserServiceComponent UserRepositoryComponent和UserServiceComponent
I added comments per my understanding. 我根据我的理解添加了评论。
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
}
}
My understanding is that the Service
depends on injection of a Repository
component. 我的理解是
Service
依赖于注入Repository
组件。
For production purposes, the following can be used to wire a "production" Repository
component into the UserServiceComponent
: 出于生产目的,可以使用以下内容将“生产”
Repository
组件连接到UserServiceComponent
:
object ComponentRegistry extends
UserServiceComponent with
UserRepositoryComponent
{
val userRepository = new UserRepository
val userService = new UserService
}
If our production code wanted to use the userRepository
or userService
, is the correct way to use them via a simple import
? 如果我们的生产代码想要使用
userRepository
或userService
,那么通过简单import
使用它们的正确方法是什么?
I think that I understand half of the article up to this point, but I'm not sure how to use the ComponentRegistry
object. 到目前为止,我认为我理解文章的一半,但我不确定如何使用
ComponentRegistry
对象。
You're running head first into the bakery of doom bro: What are some compelling use cases for dependent method types? 你首先进入了厄运兄弟的面包店: 依赖方法类型的一些引人注目的用例是什么?
To answer your question, the proper way to use userService
would be to use another trait and cake it up: 要回答你的问题,使用
userService
的正确方法是使用另一个特性并将其搞砸:
trait Example { this: UserServiceComponent =>
def getExampleUser() = userService.getUser("ExampleUser")
}
Now whatever this new trait does isn't directly coupled to anything like the object ComponentRegistry
. 现在无论这个新特性做什么都没有直接耦合到像
ComponentRegistry
这样的对象。 Instead your application becomes this: 相反,您的应用程序变为:
object Application extends
Example with
UserServiceComponent with
UserRepositoryComponent
{
val userRepository = new UserRepository
val userService = new UserService
}
Anyway, you should run for the hills because if you really want to use cake you should be doing something more like this: 无论如何,你应该跑到山上,因为如果你真的想要使用蛋糕,你应该做更像这样的事情:
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
Now save yourself some time, drop the cake pattern, and do something simple . 现在节省一些时间,放下蛋糕模式,做一些简单的事情。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.