3

我正在迈出第一步scala

我创建了一个PhotosLoaderActor负责下载图像并将其保存到缓存中的程序。为此,我将拥有 aCacheActor和 a DownloadActor

我的PhotosLoaderActor有这个:

override def act() {
  loop {
    react {
      case (caller : Actor, photoToLoad:String) => { // bla bla }

我刚刚了解到我可以使用case classes这样的东西:

case class LoadImage(caller: Actor, photoToLoad: String)
override def act() {
  loop {
    react {
      case LoadImage(caller, photoToLoad) => { // bla bla }

我的问题是:

我应该在哪里定义case classes?如果我PhotosLoaderActor从不同的包中调用,导入演员也会导入case classes? 哪个是最佳实践?

4

3 回答 3

11

我尝试了几种不同的方法,并决定将所有相关消息放入一个对象中,通常命名为 XyzProtocol 之类的东西。

例如:

object PhotoProtocol {
  case class LoadImage(caller: Actor, photoToLoad: String)
  case class UpdateCache(photoToLoad: String, photo: Photo)
  case object ClearCache
}

我喜欢这种方法有几个原因:

  1. 在 IDE 或 ScalaDoc 中扫描包含的包,仅显示 1 个或几个 XyzProtocol 对象,而不是散布着数十条消息。

  2. 如果处理消息所需的参与者数量随时间变化(例如,引入参与者池或间接到另一个参与者子树),则消息不会受到影响。

  3. 没有意外捕获参与者实例,就像在参与者类中定义案例类时那样。这种意外捕获足以让我永远不要在 actor 类中定义案例类。

注意:如果消息纯粹是一个actor的内部实现细节(例如,一个自己发送给自己的内部信号),我在actor类的伴生对象中定义消息。

PS。我还建议从标准库参与者迁移到 Akka。Akka 将被添加到 Scala 2.10 发行版中。

于 2012-05-23T02:17:30.183 回答
1

我经常将它们定义在使用它们的演员之上。或者如果多个参与者将在同一案例上匹配,则在专用于这些案例类的文件中。

package org.numbers
import akka.actor.Actor

sealed trait Numbers
case class Even(n: Int) extends Numbers
case class Odd(n: Int) extends Numbers

class NumberActor extends Actor {
  def receive = {
    case Even(n) => doEven(n)
    case Odd(n) => doOdd(n)
  }

  def doEven = ...
  def doOdd = ...
}

使用 akka 而不是 scala 演员,但无论哪种方式。这样,导入包含 actor 的包也将导入可以发送给该 actor 的消息。如果案例类是在参与者“内部”定义的,那么其他想要向该参与者发送消息的类将无法使用它们。

于 2012-05-23T01:21:50.007 回答
1

如果 Actor 是一个单例对象,那么我可能会将它放在对象本身中。

于 2012-05-23T01:34:41.920 回答