在Scala中使用存储库和接口的服务的基本设计是否相同?

时间:2014-03-12 19:24:35

标签: scala soa

在设计服务时,我通常在java中执行以下操作:

interface UserService {

}

public class UserServiceImpl implements UserService {

}

我的UserServiceImpl将使用如下的存储库:

public class UserServiceImpl implements UserService {

   @Autowired
   private IUserRepository userRepository;

}

我使用弹簧或guice进行加速注射。

如果使用Scala,我会遵循相同的模式,还是以不同的方式做事?

1 个答案:

答案 0 :(得分:1)

对于Scala中的这种东西,Cake模式存在。您可以在特征中抽象您的存储库类型,例如:

trait RepositoryModule {
  type Repository <: RepositoryLike

  val userRepository: Repository

  trait RepositoryLike { 
    // some definitions and implementation
  }
}

稍后你可以制作这个repo模块的具体版本,例如在测试的内存版本和一些真正的repo的真实版本中,例如:

trait InMemoRepoModule extends RepositoryModule {
  trait Repository extends RepositoryLike {
    // here comes module implementation
  }
}

稍后,或者在世界末日被称为&#34;&#34;,您可以混合使用此实现:

class ServiceStack extends InMemoRepoModule {
  object userRepository extends Repository
}

这是一个很好的抽象机制,因为稍后您可以使用类型构造函数进一步抽象,这是使用monad的好方法:

trait RepositoryModule[M[+_]] {
  type Repository <: RepositoryLike

  implicit val M: scalaz.Monad[M]

  val userRepository: Repository

  trait RepositoryLike { 
    def getAllusers(): M[List[User]]
  }
}

现在您通过更改monad来更改处理数据的方式,即如果在生产中您希望异步执行然后使用Future,但在测试中您需要同步执行,那么您可以使用Id来自scalaz的monad,或者如果您想检查异常,请使用Either

trait RemoteRepoModule extends RepositoryModule[Future] {
  trait Repository extends RepositoryLike {
     def getAllUsers(): Future[List[User]] = Future {
       // just implement this module
     }
   }
}

如果您想要一个实际示例如何执行此操作,请查看github上的this项目。和this这种注射机制的例子