简体   繁体   English

蛋糕图案 Scala

[英]cake pattern Scala

  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"
       

I am new in Scala and I am trying to implement the above code to print true in main.我是 Scala 的新手,我正在尝试实现上述代码以在 main 中打印 true。 My problem is that my IDE says "Not found: authenticate" and "Not found session" in trait InMemoryIdentityCache.我的问题是我的 IDE 在特征 InMemoryIdentityCache 中说“未找到:身份验证”和“未找到会话”。 I am a little confused about how to implement this cake pattern.我对如何实现这个蛋糕模式有点困惑。

I will appreciate any help.我将不胜感激。

InMemoryIdentityCache extends SessionProvider but doesn't implement session . InMemoryIdentityCache扩展了SessionProvider但没有实现session So whatever extends it would have to provide it.因此,无论扩展它都必须提供它。 From what I see only DefaultSessionProvider has it defined, but nothing mixes it in. Actually nobody mixes-in any SessionProvider as far as I can see).据我所见,只有DefaultSessionProvider定义了它,但没有任何东西将它混入其中。据我所知,实际上没有人混入任何SessionProvider )。

InMemoryIdentityCache doesn't extend Authenticator so it cannot access authenticate() . InMemoryIdentityCache不扩展Authenticator所以它不能访问authenticate() If you want to tell compiler that it should extends Authenticator and a method will be there, you need:如果你想告诉编译器它应该扩展Authenticator并且会有一个方法,你需要:

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

The fact that "final" cake might have all the methods doesn't allow you to miss them in the intermediate cake layers. “最终”蛋糕可能具有所有方法的事实不允许您在中间蛋糕层中错过它们。

Also cake pattern is widely recognized as antipattern.蛋糕模式也被广泛认为是反模式。 Rewrite your code to use constructors to inject dependencies and you'll immediately see where there are issues and why.重写您的代码以使用构造函数注入依赖项,您将立即看到问题所在以及原因。

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"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM