[英]Scala Dependency Injection with Cake Pattern
I've been following this article which describes how to achieve dependency injection in Scala via the Cake Pattern: http://jonasboner.com/real-world-scala-dependency-injection-di/ 我一直在关注这篇文章,它描述了如何通过Cake Pattern在Scala中实现依赖注入: http : //jonasboner.com/real-world-scala-dependency-injection-di/
I'm kind of new to Scala and I admit some of it went over my head, so far I've got the following working: 我对Scala有点新意,我承认其中有些事情已经过去了,到目前为止,我已经完成了以下工作:
// Setup the component and interface
trait AccountRepositoryComponent {
val accountRepository: AccountRepositoryInterface
trait AccountRepositoryInterface {
def message: String
}
}
// An implementation
trait MyAccountRepositoryComponent extends AccountRepositoryComponent {
object AccountRepository extends AccountRepositoryInterface {
def message: String = "Hello"
}
}
// Object to configure which implementations to use and retrieve them
object ComponentRegistry extends MyAccountRepositoryComponent {
val accountRepository = AccountRepository
}
// Example service using the above
object AccountService {
val repo = ComponentRegistry.accountRepository
def say: String = repo.message
}
println(AccountService.say)
What I'm failing to understand is how I would now pass in a fake repository to Account Service, say to change the output to "Test" rather than "Hello"? 我无法理解的是我现在如何将假存储库传递给帐户服务,比如将输出更改为“测试”而不是“Hello”?
There are various ways this could be modified to achieve a workable result, depending on what counts as a workable result for your situation. 可以通过多种方式对其进行修改以实现可行的结果,具体取决于您的情况可行的结果。 I'll go through a simpler possibility here.
我会在这里找到一个更简单的可能性。
First, the ComponentRegistry needs to become a trait, so it can be mixed in to the AccountService: 首先,ComponentRegistry需要成为一个特征,因此它可以混合到AccountService中:
// Trait to configure which component implementations to use and retrieve them
object ComponentRegistry extends MyAccountRepositoryComponent {
val accountRepository = AccountRepository
}
// Example service using the above
object AccountService extends ComponentRegistry {
def say: String = accountRepository.message
}
println(AccountService.say)
This should print "Hello" as before. 这应该像以前一样打印“你好”。 To set up a test case, add the following:
要设置测试用例,请添加以下内容:
// Test implementation
trait TestAccountRepositoryComponent extends AccountRepositoryComponent {
object AccountRepository extends AccountRepositoryInterface {
def message: String = "Test"
}
}
// trait to configure test component implementations
trait TestComponentRegistry extends TestAccountRepositoryComponent {
val accountRepository = AccountRepository
}
Now we can set up a service that uses the test components: 现在我们可以设置一个使用测试组件的服务:
// Example service using the above
object AccountService extends TestComponentRegistry {
//val repo = ComponentRegistry.accountRepository
def say: String = accountRepository.message
}
println(AccountService.say)
This should print "Test". 这应该打印“测试”。
Note that you would probably want your AccountService to define its functionality in terms of other mixins/traits, which would expect the appropriate components to be available (layered into the "cake"), but wouldn't know which implementation was in use. 请注意,您可能希望您的AccountService根据其他mixins / traits定义其功能,这将期望适当的组件可用(分层到“蛋糕”),但不知道正在使用哪个实现。 Eg:
例如:
trait CustomerApi {
self: AccountRepositoryComponent => // Expects an implementation of AccountRepositoryComponent to be mixed in
def say: String = accountRepository.message
}
Now the method say
is implemented without knowing what version of AccountRepository
it will interact with, but knowing one must be provided (checked at compile time). 现在
say
方法是在不知道它将与哪个版本的AccountRepository
交互的情况下实现的,但必须提供一个知道版本(在编译时检查)。 So we can write: 所以我们可以写:
object AccountService extends CustomerApi with ComponentRegistry
object TestAccountService extends CustomerApi with TestComponentRegistry
Calling println(AccountService.say)
will generate "Hello"
, while calling println(TestAccountService.say)
will generate "Test"
. 调用
println(AccountService.say)
将生成"Hello"
,而调用println(TestAccountService.say)
将生成"Test"
。
这篇文章提供了一个简洁的例子(后面是一个有趣的替代方案)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.