-1
  import scala.collection.mutable
    
   class Session
    
    trait SessionProvider:
      def session: Session
    
    trait DefaultSessionProvider extends SessionProvider:
      val dummySession = new Session
      override def session = dummySession
    
    abstract class Identity
    
    trait IdentityCache:
      def getOrAuthenticate():Session
    
    
    trait InMemoryIdentityCache extends SessionProvider:
    
      val cache = mutable.Map.empty[Session, SessionProvider]
      override def getOrAuthenticate():InMemoryIdentityCache  =
        cache.getOrElseUpdate(session, authenticate())
    
    trait Authenticator:
    
      def authenticate():Session
    
    trait UsesSAMLIdentity:
    
    
      class SAMLIdentity(val saml: String) extends Identity
    
    trait SAMLAuthenticator extends Authenticator with UsesSAMLIdentity:
      val dummySAMLIdentity = new SAMLIdentity("XXX")
      override def authenticate() = dummySAMLIdentity
    
    
    trait RoleManager:
      def hasRole(role: String): Boolean
    
    
    trait SAMLRoleManager extends RoleManager with UsesSAMLIdentity:
    
      override def hasRole(role: String): Boolean =
        val identity = getOrAuthenticate()
        identity.saml == "XXX"
    
    
    object WebApp extends SAMLRoleManager :
    
      def main(args: Array[String]): Unit =
        println(hasRole("YYY")) // Prints "true"
       

我是 Scala 的新手,我正在尝试实现上面的代码以在 main 中打印 true。我的问题是我的 IDE 在特征 InMemoryIdentityCache 中显示“未找到:身份验证”和“未找到会话”。我对如何实现这个蛋糕模式有点困惑。

我将不胜感激。

4

1 回答 1

0

InMemoryIdentityCache扩展SessionProvider但不实现session. 因此,无论扩展它都必须提供它。从我所看到的情况来看,只有DefaultSessionProvider它被定义,但没有任何东西混合它。实际上SessionProvider,据我所知,没有人混合任何东西)。

InMemoryIdentityCache不扩展Authenticator,因此无法访问authenticate(). 如果你想告诉编译器它应该扩展Authenticator并且有一个方法,你需要:

trait InMemoryIdentityCache extends ...:
  self: Authenticator =>

“最终”蛋糕可能具有所有方法的事实不允许您在中间蛋糕层中错过它们。

蛋糕模式也被广泛认为是反模式。重写您的代码以使用构造函数注入依赖项,您将立即看到问题所在以及原因。

import scala.collection.mutable
    
class Session
abstract class Identity
class SAMLIdentity(val saml: String) extends Identity


trait SessionProvider:
  def session: Session

class DefaultSessionProvider extends SessionProvider:
  val dummySession = new Session
  override def session = dummySession


trait Authenticator:
  def authenticate(): Identity // you had Session, it didn't work  

class SAMLAuthenticator extends Authenticator:
  val dummySAMLIdentity = new SAMLIdentity("XXX")
  override def authenticate() = dummySAMLIdentity // because your return SAMLIdentity


trait IdentityCache:
  // you had Session her as well, even though there is Identity in class name
  def getOrAuthenticate(): Identity 

class InMemoryIdentityCache(
  sessionProvider: SessionProvider,
  authenticator: Authenticator
) extends IdentityCache:
  val cache = mutable.Map.empty[Session, Identity] // you had [Session, SessionProvider] ?!?
  override def getOrAuthenticate(): Identity  =
    cache.getOrElseUpdate(sessionProvider.session, authenticator.authenticate())


trait RoleManager:
  def hasRole(role: String): Boolean

class SAMLRoleManager(identityCache: IdentityCache) extends RoleManager:
  override def hasRole(role: String): Boolean = 
    identityCache.getOrAuthenticate() match {
      case identity: SAMLIdentity => identity.saml == "XXX"
      case _ => false
    }


object WebApp:
    
  def main(args: Array[String]): Unit =
    val sessionProvider: SessionProvider = new DefaultSessionProvider
    val authenticator: Authenticator = new SAMLAuthenticator
    val identityCache: IdentityCache = new InMemoryIdentityCache(sessionProvider, authenticator)
    val roleManager: RoleManager = new SAMLRoleManager(identityCache)
    println(roleManager.hasRole("YYY")) // Prints "true"
于 2022-01-28T10:30:44.170 回答