我正在尝试了解蛋糕模式。
我正在阅读this博客。
该博客的示例代码为:
case class User (name:String,email:String,supervisorId:Int,firstName:String,lastName:String)
trait UserRepository {
def get(id: Int): User
def find(username: String): User
}
trait UserRepositoryComponent {
def userRepository: UserRepository
trait UserRepository {
def get(id: Int): User
def find(username: String): User
}
}
trait Users {
this: UserRepositoryComponent =>
def getUser(id: Int): User = {
userRepository.get(id)
}
def findUser(username: String): User = {
userRepository.find(username)
}
}
trait UserInfo extends Users {
this: UserRepositoryComponent =>
def userEmail(id: Int): String = {
getUser(id).email
}
def userInfo(username: String): Map[String, String] = {
val user = findUser(username)
val boss = getUser(user.supervisorId)
Map(
"fullName" -> s"${user.firstName} ${user.lastName}",
"email" -> s"${user.email}",
"boss" -> s"${boss.firstName} ${boss.lastName}"
)
}
}
trait UserRepositoryComponentImpl extends UserRepositoryComponent {
def userRepository = new UserRepositoryImpl
class UserRepositoryImpl extends UserRepository {
def get(id: Int) = {
???
}
def find(username: String) = {
???
}
}
}
object UserInfoImpl extends
UserInfo with
UserRepositoryComponentImpl
我可以通过删除Users
:
package simple {
case class User(name: String, email: String, supervisorId: Int, firstName: String, lastName: String)
trait UserRepository {
def get(id: Int): User
def find(username: String): User
}
trait UserRepositoryComponent {
def userRepository: UserRepository
trait UserRepository {
def get(id: Int): User
def find(username: String): User
}
}
trait UserInfo {
this: UserRepositoryComponent =>
def userEmail(id: Int): String = {
userRepository.get(id).email
}
def userInfo(username: String): Map[String, String] = {
val user = userRepository.find(username)
val boss = userRepository.get(user.supervisorId)
Map(
"fullName" -> s"${user.firstName} ${user.lastName}",
"email" -> s"${user.email}",
"boss" -> s"${boss.firstName} ${boss.lastName}"
)
}
}
trait UserRepositoryComponentImpl extends UserRepositoryComponent {
def userRepository = new UserRepositoryImpl
class UserRepositoryImpl extends UserRepository {
def get(id: Int) = {
???
}
def find(username: String) = {
???
}
}
}
object UserInfoImpl extends
UserInfo with
UserRepositoryComponentImpl
}
它编译得很好。
1)为什么博客中的代码如此复杂?
2)这是使用蛋糕模式的惯用方法吗?
3)为什么本例中需要Users
类?
4)那是蛋糕模式看起来的样子(看似不必要的Users
类吗?
5)或者简化版本是不是很好?
答案 0 :(得分:9)
起初它可能看起来很复杂,但是一旦你熟悉了这种模式,它就会......锅炉布和笨重。对于您的每项服务,您必须创建一个包含该服务的附带组件。因此,在提供的示例中,您有一个由UserRepository
包裹的UserRepositoryComponent
。这只是抽象,因此您需要为组件和服务实现具体实现(即UserRepositoryComponentImpl
包装UserRepositoryImpl
)。到目前为止,您只有一个可能在您的模块中使用的服务,想象创建数十个服务的努力;)
是的,这是使用该模式的惯用方式。然而,该模式还有其他变体,例如, thin cake pattern
或parfait
(Dick Wall创造的一个词)
您问的是User
,但您的代码简化是删除Users
,因此我将对其进行描述。 User
是一个简单的案例类,应该使该示例更容易理解。 Users
但这里没有必要(它只是另一个中间抽象级别),在我看来,它们给这个例子带来了一些不必要的噪音。
我想说你的简化版本确切地显示了蛋糕图案应该是什么样子。你有一个摘要UserRepository
包含在UserRepositoryComponent
内,你有这两个特征的具体实现,你有一些服务(UserInfo
)需要用户存储库(这是“注入“使用自我类型注释”。
已经回答。