简体   繁体   English

Scala,Cake Pattern和MacWire

[英]Scala, Cake Pattern, and MacWire

I've implemented an Email service using the cake pattern. 我使用蛋糕模式实现了电子邮件服务。 Here below is the EmailComponent , which provides functionality for styling the email body: 下面是EmailComponent ,它提供了为电子邮件正文设置样式的功能:

trait EmailComponent {
  def body: Body

  trait Body {
    def style(content Html): Html
  }
}

trait DefaultEmailComponent extends EmailComponent {
  def body = new DefaultBody

  class DefaultBody extends Body {
    views.html.email(content)
  }
}

... and here is the EmailServiceComponent that actually implements the Email service using an EmailComponent : ...这里是使用EmailServiceComponent实际实现电子邮件服务的EmailComponent

trait EmailServiceComponent {
  def emailService: EmailService

  trait EmailService {
    def sendEmail(from: String, recipients: Seq[String], subject: String, content: Html)
  }
}

trait DefaultEmailServiceComponent extends EmailServiceComponent {
  this: EmailComponent =>

  def emailService = new DefaultEmailService

  class DefaultEmailService extends EmailService {
    def sendEmail(from: String, recipients: Seq[String], subject: String, content: Html) {
      val htmlBody = body.style(content)
      EmailHelper.sendEmail(from, recipients, Some(subject), (None, Some(htmlBody)))
    }
  }

The code above works fine... but I was surfing on the Internet when I came across MacWire. 上面的代码工作得很好......但是当我遇到MacWire时,我正在网上冲浪。 I read some documentation here and there and found really interesting, but to be honest I haven't fully understood how to use it and how it works. 我在这里和那里阅读了一些文档,发现真的很有趣,但说实话,我还没有完全理解如何使用它以及它是如何工作的。 Having said that, how could I reimplement the example above with MacWire? 话虽如此,我怎么能用MacWire重新实现上面的例子?

Several things to consider: 需要考虑的几件事:

  1. One big difference is that the cake pattern in your example uses inheritance / class composition to satisfy dependencies and build the concrete instances, whereas with dependency injection you would mostly use delegation. 一个很大的区别是,示例中的cake模式使用继承/类组合来满足依赖关系并构建具体实例,而使用依赖注入则主要使用委托。 It's up to you to decide how tightly coupled you want the classes to be. 由您来决定您希望这些课程的紧密耦合程度。

  2. There are limitations in MacWire to wiring when using traits defined inside other traits. 在使用其他特征内定义的特征时,MacWire有限制接线。 So your Default... implementations would have to go outside of their parent traits. 因此,您的Default...实现必须超出其父特征。

  3. Upon a quick glance, it appears that MacWire cannot resolve concrete implementations of a trait (unlike Guice, a well-established dependency-injection framework for Java, where you could use bindings and annotations for that). 快速浏览一下,似乎MacWire无法解析特征的具体实现(与Guice不同,Guice是一个完善的Java依赖注入框架,您可以在其中使用绑定和注释)。 This means you'd have to use wire[DefaultEmailService] instead of wire[EmailService] . 这意味着您必须使用wire[DefaultEmailService]而不是wire[EmailService]

  4. There is no support for circular dependencies in MacWire. 在MacWire中不支持循环依赖。 In the case above, you don't have them anyway: EmailServiceComponent depends on EmailService which in turn depends on EmailComponent. 在上面的例子中,你还没有它们:EmailServiceComponent依赖于EmailService,而EmailService依赖于EmailComponent。

So, with MacWire, your code would just be classes that use other classes, like 因此,对于MacWire,您的代码只是使用其他类的类,比如

class DefaultEmailComponent extends EmailComponent { ... }
class DefaultEmailService(emailComponent: EmailComponent) extends EmailService { ... }
trait EmailServiceComponent {
    def emailService: EmailService
}
class DefaultEmailServiceComponent(val emailService: EmailService) 
                                              extends EmailServiceComponent { ... }

lazy val emailC: EmailComponent = wire[DefaultEmailComponent]
lazy val emailSvc: EmailService = wire[DefaultEmailService]
lazy val emailSvcC: EmailServiceComponent = wire[DefaultEmailServiceComponent]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM