运维开发网

DI在Scala与蛋糕模式

运维开发网 https://www.qedev.com 2020-07-29 17:50 出处:网络 作者:运维开发网整理
这个 article通过Scala的Cake Pattern解释了依赖注入. 我对这种模式的好处的理解是,特征可以与(生产对测试)混合使用静态检查. 在Bonér先生的例子中,他列出了这个完成的(每个例子)代码: UserRepositoryComponent和UserServiceComponent 我根据我的理解添加了评论. trait UserRepositoryComponent {
这个 article通过Scala的Cake Pattern解释了依赖注入.

我对这种模式的好处的理解是,特征可以与(生产对测试)混合使用静态检查.

在Bonér先生的例子中,他列出了这个完成的(每个例子)代码:

UserRepositoryComponent和UserServiceComponent

我根据我的理解添加了评论.

trait UserRepositoryComponent {
  val userRepository: UserRepository    // stand-alone component

  class UserRepository {      
    ...                      // actual implementation here
  }
} 
trait UserServiceComponent { 
  this: UserRepositoryComponent =>      //Requires a mixed-in UserRepo*Component

  val userService: UserService  

  class UserService {
    ...                      // actual implementation here
  }
}

我的理解是服务依赖于注入存储库组件.

出于生产目的,可以使用以下内容将“生产”存储库组件连接到UserServiceComponent:

object ComponentRegistry extends 
  UserServiceComponent with 
  UserRepositoryComponent 
{
  val userRepository = new UserRepository
  val userService = new UserService
}

如果我们的生产代码想要使用userRepository或userService,那么通过简单导入使用它们的正确方法是什么?

到目前为止,我认为我理解文章的一半,但我不确定如何使用ComponentRegistry对象.

你是第一次进入厄运兄弟的面包店:

What are some compelling use cases for dependent method types?

要回答你的问题,使用userService的正确方法是使用另一个特性并将其搞砸:

trait Example { this: UserServiceComponent => 
   def getExampleUser() = userService.getUser("ExampleUser")
}

现在无论这个新特性做什么都没有直接耦合到像ComponentRegistry这样的对象.相反,您的应用程序变为:

object Application extends 
  Example with
  UserServiceComponent with 
  UserRepositoryComponent 
{
  val userRepository = new UserRepository
  val userService = new UserService
}

无论如何,你应该跑到山上,因为如果你真的想要使用蛋糕,你应该做更像这样的事情:

trait UserRepositoryComponent {

  type UserRepository <: UserRepositoryLike

  val userRepository: UserRepository

  trait UserRepositoryLike {
    def getUserOrSomething()
  }

}

trait UserRepositoryComponentImpl extends UserRepositoryComponent {

  type UserRepository = UserRepositoryImpl
  val userRepository = new UserRepositoryImpl

  class UserRepositoryImpl extends UserRepositoryLike {
    override def getUserOrSomething() = ???
  }

}

trait UserServiceComponent {
  this: UserRepositoryComponent =>

  type UserService <: UserServiceLike
  val userService: UserService

  trait UserServiceLike {
    def getUserNameById(id: Int): String
  }

}

trait UserServiceComponentImpl extends UserServiceComponent {
  this: UserRepositoryComponent =>

  type UserService = UserServiceImpl
  val userService = new UserServiceImpl

  class UserServiceImpl extends UserServiceLike {
    override def getUserNameById(id: Int) = userRepository.getUserOrSomething
  }

}

trait Example {
  this: UserServiceComponent =>

  def getExampleUser() = userService.getUserNameById(1)

}

object Application extends
Example with
UserRepositoryComponentImpl with
UserServiceComponentImpl

现在节省一些时间,丢弃蛋糕模式,并做一些事情simple.

0

精彩评论

暂无评论...
验证码 换一张
取 消