1

Scala のケーキ パターンに関する記事をいくつか読んだことがありますが、基本的には理解できました。以下は、この記事からコピーしたサンプル コードです。

コンポーネント:

case class User(username:String, password: String)

trait UserRepositoryComponent {
  val userRepository: UserRepository

  class UserRepository {
    def authenticate(user: User): User = { 
      println("authenticating user: " + user)
      user
     }
    def create(user: User) = println("creating user: " + user)
    def delete(user: User) = println("deleting user: " + user)
  }
}


trait UserServiceComponent { this: UserRepositoryComponent =>
  val userService: UserService
  class UserService {
    def authenticate(username: String, password: String): User = 
      userRepository.authenticate(User(username, password))  

    def create(username: String, password: String) = 
      userRepository.create(new User(username, password))

    def delete(user: User) = 
      userRepository.delete(user)

  }
}

それらを結合するオブジェクト:

object ComponentRegistry extends 
  UserServiceComponent with 
  UserRepositoryComponent {
  val userRepository = new UserRepository
  val userService = new UserService
}

object TestingComponentRegistry extends 
  UserServiceComponent with 
  UserRepositoryComponent {
  val userRepository = mock[UserRepository]
  val userService = mock[UserService]
}

シンプルなプロジェクトならもっとシンプルにしたい。コードは次のようになります。

case class User(username:String, password: String)

class UserRepository {
  def authenticate(user: User): User = { 
    println("authenticating user: " + user)
    user
   }
  def create(user: User) = println("creating user: " + user)
  def delete(user: User) = println("deleting user: " + user)
}

class UserService(userRepository: UserRepository) {
  def authenticate(username: String, password: String): User = 
    userRepository.authenticate(User(username, password))  

  def create(username: String, password: String) = 
    userRepository.create(new User(username, password))

  def delete(user: User) = 
    userRepository.delete(user)

}

それらを組み合わせる:

object Application {
  val userService = new UserService(new UserRepository)
}

object Test {
  val userService = new UserService(mock[UserRepository]) 
}

私の質問は、私のコードを「依存関係が挿入された」として扱うことができるのでしょうか?

  1. UserServiceのコンストラクターで依存関係を宣言しました
  2. それらをさまざまな環境のオブジェクトと組み合わせます

しかし、「コンポーネント」としていくつかの特性を提供していません。

4

1 に答える 1

3

はい、あなたのコードは「依存性が注入されています」:内部で直接インスタンス化UserServiceするのではなく、コンストラクター引数として使用することになっているコンポーネントを受け取ります。UserRepositoryUserService

私見、あなたのコードはまさにDIが90%以上の確率であるはずです。Spring や Guice のような「派手な」フレームワークも、ケーキ パターンのような「派手な」デザイン パターンも必要ありません。依存関係をコンストラクターに注入するだけです。完了し、クリーンで、簡単にテストでき、別の実装に簡単に交換できます (*)。

(*): あなたの例でこれを達成するには、UserRepositoryおそらくクラスではなく特性にする必要があることに注意してください。

于 2014-06-19T14:55:21.367 に答える