4

現在、アプリケーションでケーキ パターンを使用する作業を行っています。

私がウェブ上で見つけた例では、例は一種の基本的なものですが、より複雑なニーズは含まれていません。私がやりたいことはそれほど派手ではありません。異なる実装を使用して、同じタイプの 2 つのサービスをケーキ パターン アプリケーション内に配置したいと考えています。

trait UserServiceComponent {
  self: UserRepositoryComponent =>
  val userService: UserService

  class DefaultUserService extends UserService {
    def getPublicProfile(id: String): Either[Error, User] = userRepository.getPublicProfile(id)
  }

  class AlternativeUserService extends UserService {
    def getPublicProfile(id: String): Either[Error, User] = call webservice here for exemple...
  }
}

trait UserService extends RepositoryDelegator[User] {
  def getPublicProfile(id: String): Either[Error, User]
}

一度に の 1 つの実装を使用すると問題なく動作UserServiceしますが、同時に両方の実装が必要な場合は、その方法がよくわかりません。

2 つの異なるコンポーネントを作成する必要がありますか? それぞれが異なる userService 値の名前を公開していますか? (defaultUserService/alternativeUserService)。userService私のアプリケーションには2つの異なる実装があるため、両方の実装に1つのコンポーネントを使用すると、名前を使用するときにどの実装が使用されているかを他のコンポーネントがどのように知ることができるかわかりません。

ところで、コンポーネントは への依存関係を表すUserRepositoryComponentため、すべての実装で必要というわけではありませんが、コンポーネントが 1 つしかないのは少しおかしいと思いますよね? 両方の実装を必要とする完全なアプリケーションを構築したくないと想像してください。ただし、テストのために、必要のない AlternativeUserService のみを構築する必要がUserRepositoryComponentあります。使用済み。

何をすべきか分かるように、誰かアドバイスをくれませんか?

関連する質問の種類: ケーキパターン:コンポーネントによって提供されるタイプ UserService のすべてのオブジェクトを取得する方法

ありがとう

4

1 に答える 1

8

まず最初に、 をUserServiceComponentの実装から分離する必要がありUserServiceます。

trait UserService extends RepositoryDelegator[User] {
  def getPublicProfile(id: String): Either[Error, User]
}

trait UserServiceComponent {
  val userService: UserService
}

trait DefaultUserServiceComponent extends UserServiceComponent { self: UserRepositoryComponent =>
  protected class DefaultUserService extends UserService {
    def getPublicProfile(id: String): Either[Error, User] = userRepository.getPublicProfile(id)
  }
  val userService: UserService = new DefaultUserService
}

trait AlternativeUserServiceComponent extends UserServiceComponent {
  protected class AlternativeUserService extends UserService {
    def getPublicProfile(id: String): Either[Error, User] = call webservice here for exemple...
  }
  val userService: UserService = new AlternativeUserService
}

それが冗長に見える場合は、そうです。ケーキのパターンは特に簡潔ではありません。

UserRepositoryComponentしかし、実際には必要でない場合 ( のみを使用する場合など) に依存するという問題がどのように解決されるかに注目してくださいAlternativeUserService

ここで、アプリケーションをインスタンス化するときに行う必要があるのは、 または のいずれDefaultUserServiceComponentかを混合することだけAlternativeUserServiceComponentです。

両方の実装にアクセスする必要がある場合は、実際に 2 つの userService 値の名前を公開する必要があります。実際には、次のような 3 つの名前があります。

  • DefaultUserService実装 のための defaultUserService
  • AlternativeUserService実装 のための alternativeUserService
  • 任意の実装の mainUserService UserService(アプリケーションは「混合時間」でどれを選択するか)。

例:

trait UserService extends RepositoryDelegator[User] {
  def getPublicProfile(id: String): Either[Error, User]
}

trait MainUserServiceComponent {
  val mainUserService: UserService
}

trait DefaultUserServiceComponent { self: UserRepositoryComponent =>
  protected class DefaultUserService extends UserService {
    def getPublicProfile(id: String): Either[Error, User] = userRepository.getPublicProfile(id)
  }
  val defaultUserService: UserService = new DefaultUserService
}

trait AlternativeUserServiceComponent {
  protected class AlternativeUserService extends UserService {
    def getPublicProfile(id: String): Either[Error, User] = ??? // call webservice here for exemple...
  }
  val alternativeUserService: UserService = new AlternativeUserService
}

次に、次のようにケーキをインスタンス化できます。

object MyApp 
  extends MainUserServiceComponent 
  with DefaultUserServiceComponent 
  with AlternativeUserServiceComponent 
  with MyUserRepositoryComponent // Replace with your real UserRepositoryComponent here    
{
  //val userService = defaultUserService
  val mainUserService = alternativeUserService
}

上記の例では、明示的に にアクセスする必要があるサービスはコンポーネントの依存関係として配置され ( および についてDefaultUserServiceも同様)、一部だけが必要なサービスは代わりに依存関係として配置されます。「混合時間」で、どのサービスが指すかを決定します (ここでは、実装を指します。DefaultUserServiceComponentAlternativeUserServiceAlternativeUserServiceComponent UserServiceMainUserServiceComponentmainUserServiceDefaultUserService

于 2013-01-26T12:14:40.480 に答える