蛋糕模式可以用于非单例样式依赖吗?
我遇到的大多数蛋糕模式示例似乎都将依赖关系视为单例类型服务;其中,在组件的最终组装中每种类型只有一个实例。当使用蛋糕模式进行依赖注入时,是否可以编写一个具有多个特定类型实例的配置,可能以不同的方式配置?
考虑以下组件。通用 HTTP 服务:
trait HttpService { def get(query:String):String }
trait HttpServiceComponent {
val httpService:HttpService
class HttpServiceImpl(address:String) extends HttpService {
def get(query:String):String = ...
}
}
贸易和服务公司服务,每个都依赖于 HttpService,可能是不同的实例:
trait TradeService { def lastTrade(symbol:String):String }
trait TradeServiceComponent {
this:HttpServiceComponent => // Depends on HttpService
val tradeService:TradeService
class TradeServiceImpl extends TradeService {
def lastTrade(symbol:String):String =
httpService.get("symbol=" + symbol)
}
}
trait CompanyService { def getCompanySymbols(exchange:String):String }
trait CompanyServiceComponent {
this:HttpServiceComponent => // Depends on different HttpService instance
val companyService:CompanyService
class CompanyServiceImpl extends CompanyService {
def getCompanySymbols(exchange:String):String =
httpService.get("exchange=" + exchange)
}
}
依赖于 Trade & 的主应用程序组件;公司服务:
trait App { def run(exchange:String):Unit }
trait AppComponent {
this:CompanyServiceComponent with TradeServiceComponent =>
val app:App
class AppImpl extends App {
def run(exchange:String) =
companyService.getCompanySymbols(exchange).split(",").foreach(sym => {
val lastTrade = tradeService.lastTrade(sym)
printf("Last trade for %s: %s".format(sym, lastTrade))
})
}
}
是否可以连接应用程序,使其 TradeService 使用指向一个地址的 HttpService,而其 CompanySerivce 使用指向另一个地址的不同 HttpService 实例?
Most of the examples of the Cake Pattern I've come across appear to consider dependencies as singleton type services; where there is only one instance of each type in the final assembly of components. Is it possible to write a configuration that has more than one instance of a particular type, perhaps configured in different ways, when using the Cake Pattern for dependency injection?
Consider the following components. Generic HTTP service:
trait HttpService { def get(query:String):String }
trait HttpServiceComponent {
val httpService:HttpService
class HttpServiceImpl(address:String) extends HttpService {
def get(query:String):String = ...
}
}
Trade & Company services, that each depend on an HttpService, which may be different instances:
trait TradeService { def lastTrade(symbol:String):String }
trait TradeServiceComponent {
this:HttpServiceComponent => // Depends on HttpService
val tradeService:TradeService
class TradeServiceImpl extends TradeService {
def lastTrade(symbol:String):String =
httpService.get("symbol=" + symbol)
}
}
trait CompanyService { def getCompanySymbols(exchange:String):String }
trait CompanyServiceComponent {
this:HttpServiceComponent => // Depends on different HttpService instance
val companyService:CompanyService
class CompanyServiceImpl extends CompanyService {
def getCompanySymbols(exchange:String):String =
httpService.get("exchange=" + exchange)
}
}
Main app component that depends on Trade & Company services:
trait App { def run(exchange:String):Unit }
trait AppComponent {
this:CompanyServiceComponent with TradeServiceComponent =>
val app:App
class AppImpl extends App {
def run(exchange:String) =
companyService.getCompanySymbols(exchange).split(",").foreach(sym => {
val lastTrade = tradeService.lastTrade(sym)
printf("Last trade for %s: %s".format(sym, lastTrade))
})
}
}
Is it possible to wire up the App so that its TradeService uses a HttpService that points to one address, and its CompanySerivce uses a different HttpService instance pointing to another address?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
正如您从答案中看到的那样(尤其是丹尼尔的答案,还有您自己的答案),这是可能的,但看起来并不优雅。之所以出现困难,是因为当您使用 Cake 模式时,您将所有必需的特征混合到一个对象中(使用“with”关键字),并且您不能将一种特征多次混合到一个实例中。这就是 mixins 的工作原理,而 Cake 就是基于它们的。
您可以强制 Cake 处理非单例依赖项这一事实并不意味着您应该这样做。我建议您在这种情况下简单地使用普通的构造函数,这就是自我类型注释不太适合的地方:
App 和 AppComponent 特征保持其原始形式。现在您可以按以下方式使用所有组件:
此外,您可能需要仔细检查 Cake 模式是否真的最适合您的需求,因为它实际上是一种复杂的模式,依赖项注入只是其中的一部分。如果您仅将其用于 DI,我建议您使用更简单的解决方案。我在博客上写过在这里。
As you can see from the answers (notably Daniel's, but also your own), it is possible, but it doesn't look elegant. The difficulty appears because when you use the Cake pattern, you mix all required traits into one object (using "with" keyword), and you cannot mix a trait more than once into one instance. That is how mixins work, and the Cake is based on them.
The fact you can force Cake to handle non-singleton dependencies doesn't mean you should do it. I would advise you to simply use plain-old constructor in such cases, that is where self-type annotation doesn't fit well:
The App and AppComponent traits stay in their original form. Now you can use the all components in the following way:
Also, you may want do double-check if the Cake pattern is really best suited for your needs, as it is actually a complex pattern and dependency injection is only one part of it. If you use it only for DI, I would advise you to use a simpler solution. I've blogged about that here.
由于每个“客户端”可能需要不同的实现,因此您只需参数化服务即可。
像这样使用:
最终的混合将执行如下操作:
Since each "client" may need a different implementation, you could just parameterize the service.
To be used like this:
The final mix would then do something like this:
这可以按预期编译和运行,但还有很多不足之处:
This compiles and runs as expected, but it leaves a lot to be desired: