2012-12-01 35 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?

...它打算成为一个很好格式化的回答戴夫格里菲斯的代码