Scala,Cake Pattern和MacWire

时间:2013-12-28 16:45:49

标签: scala dependency-injection

我使用蛋糕模式实现了电子邮件服务。下面是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)
  }
}

...以下是使用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)))
    }
  }

上面的代码工作得很好......但是当我遇到MacWire时,我正在网上冲浪。我在这里和那里阅读了一些文档,发现真的很有趣,但说实话,我还没有完全理解如何使用它以及它是如何工作的。话虽如此,我怎么能用MacWire重新实现上面的例子?

1 个答案:

答案 0 :(得分:2)

需要考虑的几件事情:

  1. 一个很大的区别是你的例子中的蛋糕模式使用继承/类组合来满足依赖关系并构建具体实例,而使用依赖注入你将主要使用委托。由您来决定您希望课程的紧密耦合程度。

  2. 使用定义的特征时,MacWire的连线存在限制 在其他特质中。所以你的Default...实现必须这样做 超出他们的父母特质。

  3. 快速浏览一下,似乎MacWire无法解析混凝土 特质的实现(与Guice不同,一个成熟的 Java的依赖注入框架,您可以使用它 绑定和注释)。这意味着您必须使用wire[DefaultEmailService]代替wire[EmailService]

  4. 在MacWire中不支持循环依赖。在上面的例子中,你还没有它们:EmailServiceComponent依赖于EmailService,而EmailService依赖于EmailComponent。

  5. 因此,对于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]