在设计服务时,我通常在java中执行以下操作:
interface UserService {
}
public class UserServiceImpl implements UserService {
}
我的UserServiceImpl将使用如下的存储库:
public class UserServiceImpl implements UserService {
@Autowired
private IUserRepository userRepository;
}
我使用弹簧或guice进行加速注射。
如果使用Scala,我会遵循相同的模式,还是以不同的方式做事?
答案 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
}
}
}