Зачем использовать шаблон scala cake вместо абстрактных полей?

Я читал о внедрении зависимостей в scala через шаблон cake . Я думаю, что понимаю это, но я, должно быть, что-то упустил, потому что до сих пор не вижу в этом смысла! Почему предпочтительнее объявлять зависимости через собственные типы, а не только через абстрактные поля?

В примере из Programming Scala TwitterClientComponent объявляет подобные зависимости с помощью шаблона торта:

//other trait declarations elided for clarity
...

trait TwitterClientComponent {

  self: TwitterClientUIComponent with
        TwitterLocalCacheComponent with
        TwitterServiceComponent =>

  val client: TwitterClient

  class TwitterClient(val user: TwitterUserProfile) extends Tweeter {
    def tweet(msg: String) = {
      val twt = new Tweet(user, msg, new Date)
      if (service.sendTweet(twt)) {
        localCache.saveTweet(twt)
        ui.showTweet(twt)
      }
    }
  }
}

Как это лучше, чем объявление зависимостей в виде абстрактных полей, как показано ниже?

trait TwitterClient(val user: TwitterUserProfile) extends Tweeter {
  //abstract fields instead of cake pattern self types
  val service: TwitterService
  val localCache: TwitterLocalCache
  val ui: TwitterClientUI

  def tweet(msg: String) = {
    val twt = new Tweet(user, msg, new Date)
    if (service.sendTweet(twt)) {
      localCache.saveTweet(twt)
      ui.showTweet(twt)
    }
  }
}

Глядя на время создания экземпляра, когда на самом деле происходит DI (насколько я понимаю), я изо всех сил пытаюсь увидеть преимущества торта, особенно если учесть дополнительную клавиатуру, вводящую вас необходимо сделать для деклараций торта (включающий признак)

    //Please note, I have stripped out some implementation details from the 
    //referenced example to clarify the injection of implemented dependencies

    //Cake dependencies injected:
    trait TextClient
        extends TwitterClientComponent
        with TwitterClientUIComponent
        with TwitterLocalCacheComponent
        with TwitterServiceComponent {


      // Dependency from TwitterClientComponent:
      val client = new TwitterClient

      // Dependency from TwitterClientUIComponent:
      val ui = new TwitterClientUI

      // Dependency from TwitterLocalCacheComponent:
      val localCache = new TwitterLocalCache 

      // Dependency from TwitterServiceComponent
      val service = new TwitterService
    }

Теперь снова с абстрактными полями, более или менее то же самое!:

trait TextClient {
          //first of all no need to mixin the components

          // Dependency on TwitterClient:
          val client = new TwitterClient

          // Dependency on TwitterClientUI:
          val ui = new TwitterClientUI

          // Dependency on TwitterLocalCache:
          val localCache = new TwitterLocalCache 

          // Dependency on TwitterService
          val service = new TwitterService
        }

Я уверен, что мне что-то не хватает о превосходстве торта! Однако на данный момент я не вижу, что он предлагает по сравнению с объявлением зависимостей каким-либо другим способом (конструктор, абстрактные поля).

25
задан Noel Kennedy 11 August 2011 в 12:49
поделиться