Scala - 伴随对象中的依赖注入

时间:2016-12-09 08:25:50

标签: scala playframework dependency-injection guice

我来自Java背景,并且是功能范例的新手,所以请原谅并纠正我,我闻起来像OOP。

我有一个特征名称PaymentHandler

trait PaymentHandler {

def handleInit(paymentInfo: PaymentInfo, paymentConfig: PaymentConfig): Either[Future[WSResponse], Exception]

def handleComplete(paymentinfo: PaymentInfo, paymentConfig: PaymentConfig, clientToken: String): Future[Map[String, String]]

}

@Singleton
class PayPal extends PaymentHandler{....}
@Singleton
class BrainTree extends PaymentHandler{....}

直到这里一切都很好。但问题来自于我希望基于Payment方法拥有多个PaymentGateways。 最初我写了一个像

这样的PaymentHandlerFactory
class PaymentHandlerFactory @Inject()(
    paypal:PayPal,
    braintree:BrainTree) {

  def get(name:String): PaymentHandler = {
     name match {
       case "paypal" => paypal
       case "bt" => braintree
       case _ => null
     }
  }
}

然后使用此PaymentHandlerFactory获取guice注入的PayPal对象。但不知何故,我觉得这不是正确的方法,我得到了伴侣。所以这是我写的代码

object PaymentHandler {
  @Inject
  val paypal:PayPal = null

  def apply(name:String): PaymentHandler = {
    name match {
      case "paypal" => paypal
      case _ => null
    }
  }
}

当然这会失败,因为它无法注入PayPal对象。现在我脑子里有两个问题。

  1. 为什么我们不能在scala中注入伴随对象?
  2. 在scala中实现像工厂这样的工厂的正确方法是什么?

2 个答案:

答案 0 :(得分:1)

  1. 无法注入伴随对象的原因是因为它们是对象而不是类。这意味着只存在一个实例,并且由scala本身创建。如果要进行依赖项注入,则必须通过依赖项注入框架创建需要依赖项的事物。因此,如果你想使用guice,你需要使用类来模拟你的死亡。

  2. 我认为您对class PaymentHandlerFactory所做的是务实的方式,并且可能在大多数情况下有效。我不会过早地使这个过于通用。

  3. 如果你想让它变得更加明智,你可以使用他们的AssistedInject

答案 1 :(得分:0)

如果您对伴随对象上的DI提出了疑问,请检查以下变通方法

  • 将相应的类与DI一起使用
  • 在此类上创建一个伴随对象

DI的好处是它将被传播到该伴随对象。

如果您在class Paypalclass BrainTree上有一个伴随对象,如下所示:

@Singleton
class PayPal extends PaymentHandler{....}
object PayPal extends PayPal
@Singleton
class BrainTree extends PaymentHandler{....}
object BrainTree extends BrainTree

现在,我可以在PaymentHandler伴随对象中使用这些对象,如下所示:

// get the correct handler from factory
class PaymentHandler extends PaymentHandlerFactory(PayPal, BrainTree){...}
object PaymentHandler extends PaymentHandler

现在在任何课程中,我们都可以使用PaymentHandler.get()