我通常使用traits来实现策略(某些操作不需要附带的字段)。最近我发现可以根据对象定义相同的功能。除了apply()
之外,它们可能直接扩展Function trait或扩展一些定义特殊方法的特性示例代码:
/* 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 :(得分:4)
在您描述的用例中,使用特征或对象是不必要的面向对象的过度杀伤。您的策略只是功能,并且可以最干净地实施。
object Strategy{
type Strategy = () => Unit
val sayA:Strategy = ()=>{println("A")}
val sayB:Strategy = ()=>{println("B")}
val sayC:Strategy = ()=>{println("C")}
}
在这里创建Function0 [Unit]的子类只是不会给你带来任何东西,并且使你有能力制作琐碎的文字。函数是Scala中非常好的实体。对它们感到舒服,并且不要犹豫直接使用它们。
答案 1 :(得分: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只包含对不同函数的调用,那么如果有人告诉我们如何通过AST将这些调用发送到sayA,sayB,sayC会很好吗?
......它的目的是为Dave Griffith的代码提供格式良好的答案