我的第一步是scala
。
我创建了一个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
,导入actor还会导入case classes
?哪种是最佳做法?
答案 0 :(得分:11)
我尝试了一些不同的方法,并决定将所有相关的消息放入一个对象,通常命名为XyzProtocol。
例如:
object PhotoProtocol {
case class LoadImage(caller: Actor, photoToLoad: String)
case class UpdateCache(photoToLoad: String, photo: Photo)
case object ClearCache
}
我喜欢这种方法有几个原因:
在IDE或ScalaDoc中扫描包含的包只显示一个或几个XyzProtocol对象,而不是散落着几十条消息。
如果处理消息所需的参与者数量随时间而变化(例如,引入actor池或间接到另一个actor子树),则消息不会受到影响。
没有意外捕获actor实例,就像在actor类中定义case类一样。这种意外捕获足以让我永远不会在actor类中定义case类。
注意:如果消息纯粹是actor的内部实现细节(例如,自身发送给自身的内部信号),我在actor类的伴随对象中定义消息。
PS。我还建议从标准图书馆演员那里搬到Akka。 Akka将被添加到Scala 2.10发行版中。
答案 1 :(得分:1)
我经常在使用它们的actor上面定义它们。或者在专用于这些案例类的文件中,如果多个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 actor,但无论如何。这样,导入包含actor的包也将导入可以发送给该actor的消息。如果案例类是在actor的“内部”定义的,那么它们将无法用于其他想要向该actor发送消息的类。
答案 2 :(得分:1)
如果Actor是一个单例对象,那么我可能会将它放在对象本身内。