我已经读过这篇文章几次:
http://jonasboner.com/2008/10/06/real-world-scala-dependency-injection-di.html
我想我明白了。但是,有些事情我还不太了解。
查看他的UserService示例,我看到他设置了UserRepositoryComponent来封装UserRepository。但是我不明白的是为什么UserRepositoryComponent扮演两个角色:它封装了UserRepository,还提供了对UserRepository对象的引用。
我试图想象如果我想创建一个依赖于两个UserRepository实例的服务,我将如何使用这种模式。也许新服务的工作是将用户从“源” UserRepository复制到“目标” UserRepository。所以我在想像这样的事情:
trait CopyUserServiceComponent {
val source: UserRepositoryComponent
val destination: UserRepositoryComponent
class CopyUserServiceComponent {
...
}
}
但这与原始模式不同。在这种情况下,我要在组件本身中定义依赖项,而不是从其他某个组件继承它们。但这在我看来是正确的方法:组件应声明其依赖关系,而不是声明其包含的服务的实例。
我在这里想念什么?
最佳答案
蛋糕模式不使用继承来声明依赖关系。您在UserServiceComponent
中看到任何“扩展”了吗?
但这正是蛋糕模式所做的:声明依赖项!也许如果示例包含def userRepositoryFactory = new UserRepository
而不是val userRepository = new UserRepository
,那会更清楚吗?
因此,让我们回到您的示例:
trait CopyUserServiceComponent {
val source: UserRepositoryComponent
val destination: UserRepositoryComponent
class CopyUserServiceComponent {
...
}
}
让我们看看我们无法做到的事情:
trait CopyUserServiceComponent {
// The module will need to see my internals!
private val source: UserRepositoryComponent
private val destination: UserRepositoryComponent
class CopyUserServiceComponent {
...
}
}
trait CopyBigUserServiceComponent extends CopyServiceComponent {
// Any change in implementation will have to be reflected in the module!
val tmp: UserRepositoryComponent
...
}
另一方面...
trait UserRepositoryComponent {
val userRepositoryFactory: () => UserRepository
class UserRepository {
...
}
}
trait CopyUserServiceComponent {
self: UserRepositoryComponent =>
// No problem here
private val source: UserRepository = userRepositoryFactory()
private val destination: UserRepository = userRepositoryFactory()
class CopyUserServiceComponent {
...
}
}
trait CopyBigUserServiceComponent extends CopyServiceComponent {
self: UserRepositoryComponent =>
// No problem here either
val tmp: : UserRepository = userRepositoryFactory()
...
}
编辑
为了补充答案,让我们考虑两个不同的需求:
UserRepository
的许多实例。 在这种情况下,您将以错误的级别应用模式。在Jonas的示例中,
UserRepository
处于工厂提供的单例级别。因此,在那种情况下,您将不会执行
UserRepository
和UserRepositoryComponent
,而是说UserRepositoryFactory
和UserRepositoryFactoryComponent
。UserRepository
。 在这种情况下,只需执行以下操作:
trait UserRepositoryComponent {
val sourceUserService: UserService
val destinationUserService: UserService
class UserService ...
}
关于scala - 乔纳斯·博内尔(JonasBonér)的依赖注入(inject)策略似乎很局限-但也许我不明白,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4078991/