2012-12-01 34 views
4

我通常使用特徵實施策略(一些行動,不需要附帶的領域)。最近我發現可以用對象來定義相同的功能。它們可直接擴展功能性狀或應用()什麼是最好的策略在斯卡拉:對象或特質

示例代碼擴展預留一些特質定義特殊的方法:

/* strategy realization via traits */ 
package object Traitness { 
    trait Strategy { 
    def performAction() : Unit =() 
    } 
    abstract class Usage {_ : Strategy => 
    def doWork() = 
    this.performAction() 
    } 

    // defining strategies 
    trait SayA extends Strategy { 
    override def performAction() = { 
     println("A") 
     super.performAction() 
    } 
    } 

    trait SayB extends Strategy { 
    override def performAction() = { 
     println("B") 
     super.performAction() 
    } 
    } 

    trait SayC extends Strategy { 
    override def performAction() = { 
     println("C") 
     super.performAction() 
    } 
    } 

    //using strategies 
    class SimpleStrategy extends Usage with SayA 
    def reverseOrder() = new Usage with SayC with SayA 
    object fullUsage extends Usage with SayA with SayB with SayC 

    //run-time checking 
    val check1 : Boolean = (new SimpleStrategy).isInstanceOf[SayB] 
    val check2 : Boolean = reverseOrder().isInstanceOf[SayB] 
    val check3 : Boolean = fullUsage.isInstanceOf[SayB] 

    //compile-time checking 
    def proclaim(x : SayB) = println("SayB") 
} 

/* strategy realization via function objects */ 
package object Valueness { 
    trait Strategy extends Function0[Unit] 

    class Usage(val strategies : List[Strategy]) { 
    def doWork() = for (s <- strategies) 
     s() 
    } 

    //defining strategies 
    object SayA extends Strategy { 
    override def apply() = { 
     println("A") 
    } 
    } 

    object SayB extends Strategy { 
    override def apply() = { 
     println("B") 
    } 
    } 

    object SayC extends Strategy { 
    override def apply() = { 
     println("C") 
    } 
    } 

    //using strategies 
    class SimpleStrategy extends Usage(SayA :: Nil) 
    def reverseOrder() = new Usage(SayB :: SayA :: Nil) 
    val fullUsage = new Usage(SayA :: SayB :: SayC :: Nil) 

    //run-time checking 
    def check(strategy : Strategy, usage : Usage) = usage.strategies contains strategy 
    val check1 : Boolean = check(SayB, new SimpleStrategy) 
    val check2 : Boolean = check(SayB, reverseOrder()) 
    val check3 : Boolean = check(SayB, fullUsage) 

    //no compile-time checking available 
} 

哪一個我應該選擇?

+0

這是非常相似的成分(proxy'ing來處理不同的策略對象)與繼承(其中實現不同性狀混合戰略)..我認爲這不是天生「最好」(或「更可取」),不同的情況可能適合不同的策略。 – 2012-12-01 18:37:55

+0

使用自我類型不是強制性的。我可以混合使用策略,並將它們作爲類型策略的類成員包含在用法中。 – ayvango

回答

4

在你描述的用例中,使用特徵或對象是不必要的面向對象的過度殺傷。你的策略是簡單的功能,並且可以像這樣乾淨地執行。

object Strategy{ 

    type Strategy =() => Unit 

    val sayA:Strategy =()=>{println("A")} 
    val sayB:Strategy =()=>{println("B")} 
    val sayC:Strategy =()=>{println("C")} 
} 

創建Function0 [單位]這裏的一個子類只是不買任何東西,並且收費是你做瑣碎文字的能力。函數是Scala中完美的實體。讓他們舒服,不要猶豫直接使用它們。

+1

有時我需要在策略中有三個功能:開始,過程,結束。這是一個相當簡單的例子。創建Function0 [Unit]的子類給了我編譯時的類型檢查的能力(例如爲不同的物理變量分配不同的類型) – ayvango

+0

鑑於這一點,我仍然不確定通過子類化Function0得到的結果,因爲您的策略對象不是'實際上就像功能一樣。 –

0
class MyStrategy { 
    val sayABC: Strategy.Strategy =() => { 
    Strategy.sayA() 
    Strategy.sayB() 
    Strategy.sayC() 
    } 
} 
reflect.runtime.universe.typeOf[MyStrategy].members.filter(_.asTerm.fullName.endsWith(".sayABC")).head 

結果:

res36: reflect.runtime.universe.Symbol = value sayABC 

的情況下,如果我的功能sayABC只包括調用不同的功能,這將是很好,如果有人告訴我們如何去沙耶,sayB這些電話, sayC通過AST?

...它打算成爲一個很好格式化的回答戴夫格里菲斯的代碼