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

Scala - Dependency injection in companion objects

我来自 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{....}

至此一切正常。但是当我想要基于付款方式的多个 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 中实现类似工厂的正确方法是什么?
  1. 你不能注入伴随对象的原因是因为它们是对象而不是 classes。这意味着只存在一个实例,它是由 scala 本身创建的。如果要做依赖注入,那么需要依赖的东西就必须由依赖注入框架创建。因此,如果您想使用 guice,您需要使用 class 为工厂建模。

  2. 我认为您对 class PaymentHandlerFactory 所做的是务实的方式,并且可能在大多数情况下都有效。我会避免过早地使它过于笼统。

如果你想让它更简单一点,你可以使用他们的AssistedInject

如果您遇到有关伴随对象上的 DI 的问题,请查看以下解决方法

  • 使用相应的 class 和 DI
  • 在此class
  • 上创建一个伴随对象

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

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