2012-05-23 19 views
3

我正在用scala来完成我的第一步。在使用Actor时何处定义案例类

我已经创建了一个PhotosLoaderActor,它将负责下载图像并将其保存到缓存中。要做到这一点,我将有一个CacheActor和一个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?最佳做法是什么?

回答

10

我已经尝试了几种不同的方法,并决定将所有相关消息放入一个对象中,通常名称类似于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类中的case类时那样。这种意外的捕获足以让我永远不会在演员类中定义案例类。

注意:如果该消息是纯粹动作者(例如,内部信号通过自身发送到本身)的内部实现细节,我定义在演员类的同伴对象的消息。

PS。我也建议从标准库演员转到阿卡。 Akka将被添加到Scala 2.10发行版中。

1

我经常在使用它们的actor上面定义它们。或者,如果多个参与者在相同案例中匹配,则专门用于这些案例类。

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 actors,但无论如何。这样,导入包含actor的包也将导入可发送给该actor的消息。如果案例类被定义在演员的“内部”,那么他们将不会被其他想要向该演员发送消息的类使用。

1

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

相关问题