【问题标题】:Replace only repositories on a global cake pattern application仅替换全局蛋糕模式应用程序上的存储库
【发布时间】:2013-01-09 21:23:32
【问题描述】:

我是第一次尝试使用蛋糕图案。

我有点理解它的工作原理,但想知道是否可以混合已经混合的特征或类似的东西。

我想要的是用蛋糕模式构建一个全局应用程序。 而且我想要该应用程序的另一个版本,除了存储库级别之外,它是相同的。

是否可以这样做:

  trait application extends DefaultUserServiceComponent with MongoUserRepositoryComponent

  object realApplication extends application
  object fakeApplication extends FakeUserRepositoryComponent with application

我的意思是:在使用假存储库构建假应用程序时重用已经构建的应用程序?

【问题讨论】:

    标签: scala mixins cake-pattern


    【解决方案1】:

    简短回答:不。您将继承相互冲突的成员。见以下代码sn -p:

    trait Repository {def authenticate(username: String, password: String): String}
    
    trait UserServiceComponent {self: UserRepositoryComponent =>
      val userService: UserService = new UserService
      class UserService {
        def authenticate(username: String, password: String): String =
          repository.authenticate(username, password)
      }
    }
    
    trait UserRepositoryComponent {
      def repository: Repository
    }
    
    trait MongoUserRepositoryComponent extends UserRepositoryComponent {
      val repository: Repository =
        new Repository {def authenticate(username: String, password: String) = "MongoAuthed"}
    }
    
    trait MockUserRepositoryComponent extends UserRepositoryComponent {
      val repository: Repository =
        new Repository {def authenticate(username: String, password: String) = "MockAuthed"}
    }
    
    trait Application extends UserServiceComponent with MongoUserRepositoryComponent
    
    object RealApplication extends Application
    // The following will be an error: "object FakeApplication inherits conflicting members:"
    object FakeApplication extends Application with MockUserRepositoryComponent
    

    相反,要获得所需的行为,请将 Application 定义为:

    trait Application extends UserServiceComponent {self: UserRepositoryComponent =>}
    object RealApplication extends Application with MongoUserRepositoryComponent
    object FakeApplication extends Application with MockUserRepositoryComponent
    

    要保持 OP 中给出的层次结构,您需要修改代码:

    trait MongoUserRepositoryComponent extends UserRepositoryComponent {
      private val _repository = new Repository {def authenticate(username: String, password: String) = "MongoAuthed"}
      def repository: Repository = _repository
    }
    
    trait MockUserRepositoryComponent extends UserRepositoryComponent {
      private val _repository = new Repository {def authenticate(username: String, password: String) = "MockAuthed"}
      def repository: Repository = _repository
    }
    
    trait Application extends UserServiceComponent with MongoUserRepositoryComponent
    
    object RealApplication extends Application
    object FakeApplication extends Application with MockUserRepositoryComponent {
      override val repository: Repository = super[MockUserRepositoryComponent].repository
    }
    

    额外的private val _repository 是必要的,这样我们就可以将repository 定义为一个函数,这样它就可以在FakeApplication 中用作覆盖。 (使用super[type] 覆盖仅适用于函数)。

    编辑:最后,蛋糕模式的目的是开发一个不需要像我提供的最后一个代码 sn-p 那样覆盖的层次结构。实际上,特征Application 根本不应该存在,只有RealApplicationFakeApplication。 (在第二个代码 sn-p 中,我基本上只是将 UserServiceComponent 重命名为 Application)。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-02
    • 1970-01-01
    • 1970-01-01
    • 2011-08-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多