我来自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对象。现在我心中有两个问题。
之所以无法注入伴随对象,是因为它们是对象而不是类。这意味着仅存在一个实例,并且由scala本身创建。如果要进行依赖项注入,则必须由依赖项注入框架创建需要依赖项的事物。因此,如果您想使用guice,则需要使用一个类来为您的虚构模型建模。
我认为您对class PaymentHandlerFactory
所做的工作是务实的方式,可能在大多数情况下都可以使用。我不要过早地使它变得太通用。
如果您想使其更具趣味性,可以使用其AssistedInject。
如果您遇到有关伴随对象上的DI的问题,请检查以下解决方法
DI的好处是它将被传播到此伴随对象。
如果您在class Paypal
和class 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