2014-01-23 48 views
3

我在阿卡建立的代碼庫工作,我看到這種模式有很多:任何避免在Akka伴侶對象中定義道具方法的方法?

class Bar(a: A, b: B, c: C) extends Actor { 
    // body of actor 
} 

object Bar { 
    def props(a: A, b: B, c: C) = Props(new Bar(a = a, b = b, c = c) 
} 

但道具方法感覺醜陋像Java中一個getter/setter方法。有一個更好的方法嗎?

我認爲這將有可能直接例如創建演員

var child = context.actorOf(Props(new Bar(a, b, c)) 

由於這不是比使用道具的版本要複雜得多:

var child = context.actorOf(Bar.Props(a, b, c)) 

但是,如果我理解這個職位上Deprecation of Closures Taking Props那麼這是不好的做法。相反,他們主張使用:

var child = context.actorOf(Props(classOf[Bar], a, b, c)) 

但是,那麼這會遭受重構問題,如Ryan概述如下?

+3

將「Props」放置在伴侶對象中使其更接近它所構造的actor的定義,並且稍後可以更輕鬆地重構該actor,因爲您不會在同一個actor中存在多個「Props」。 – Ryan

+0

嗨,瑞恩!我觀察完全相反。這個構造使得重構變得更糟,因爲現在我需要改變所有構造函數和道具方法。除非這裏有其他限制,我不明白?你能多解釋一下嗎? –

+0

你誤會了。你的第一個例子是我所倡導的,而不是你添加到你的文章中的那個。 – Ryan

回答

3

除了保持Props創作更接近演員的類,它也可以避免不小心關閉了一個演員的this參考,因爲如果你使用Props(new MyActor("foo"))另一名演員中會發生。

most recent reference guide section on Props

這也避免了與使用 Props.apply(...)方法,這需要通過-name參數,相關的缺陷,因爲一個 伴侶內對象的給定碼塊不會保留對其封閉範圍的參考 。

如果你真的不想使用配套對象.props並希望創建另一個演員裏面Props那麼你應該使用這個版本的Props創造者的安全:

def apply(clazz: Class[_], args: Any*) 

例如:

context.actorOf(Props(classOf[MyActor], "foo")) 

明顯的缺點是它沒有提供參數的類型檢查。

3

的主要原因,以保持它更接近類是由於反射涉及您不想反射調用周圍地勢都在你的代碼庫,因爲在你的演員的構造函數可以在運行時打破東西一個變化你希望堆棧跟蹤儘可能地接近你的問題(順便說一下,在你的例子中,你似乎沒有使用Actor構造的反射方式)。

編輯

object MyActor { 
    def props(param: Int): Props = Props(classOf[MyActor], param) 
} 

class MyActor(param: Int) extends Actor { 
    def receive = ... 
} 

如果你要改變的MyActor構造接受如額外的參數,像這樣:

class MyActor(param: Int, param2: String) extends Actor { ... } 

您的代碼會編譯得很好,但在運行時的反射API將無法找到這麼一個會拋出異常,從Props(classOf[MyActor], param)呼叫相匹配的公共構造函數,你將在日誌中看到一個堆棧跟蹤。您希望堆棧跟蹤儘可能接近問題的根源,以便您可以更快地找到問題或解決問題。如果每個人都使用props工廠方法,唯一的地方,你所有的堆棧跟蹤(如果有的話)會導致你會的,很好的定義,props工廠方法。

+0

嗨agilesteel。對不起,我不明白 - 請你可以舉一些例子代碼?我猜你通常會在運行時不知道actor的類型時使用反射。情況並非如此。 –

+0

我更新了答案。 – agilesteel