在Strategy模式中,实现如下:
object StrategyPattern {
def add(a: Int, b: Int) = a + b
def subtract(a: Int, b: Int) = a - b
def multiply(a: Int, b: Int) = a * b
def execute(callback:(Int, Int) => Int, x: Int, y: Int) = callback(x, y)
def main(args: Array[String]) {
println("Add: " + execute(add, 3, 4))
println("Subtract: " + execute(subtract, 3, 4))
println("Multiply: " + execute(multiply, 3, 4))
}
}
我想知道(并找到如何理解其他情况,如果有一个很好的参考绑定时间的类型/形式)如果方法add, substract, and multiply
的绑定时间是"construction time"
(如果我可以这样说),还是在runtime
?
简单的答案是(对于具体的类)方法定义在编译时绑定到方法名,就像在Java中一样。例如,您的add
方法完全等同于这个Java定义:
public int add(int a, int b) {
return a + b;
}
<<p> 不是final方法/strong> 如果您从调用站点的角度分析非final方法的绑定时间,其中具体类不是静态已知的,那么该方法名称将被认为与其实现具有运行时绑定(由于子类化/重写)。
动态类加载这个简单的答案接近事实,但是JVM中的动态类加载使事情变得复杂了一点。由于动态类加载,方法定义在技术上在运行时被绑定到完全限定名(例如,my.pkg.StrategyPattern.add
)。当然可以有my.package.StrategyPattern
模块的替代实现,并动态地在其中选择(通过加载相应的类文件)。
当然,这种区别只与包含StrategyPattern
定义的编译单元之外的代码相关。在编译单元内,方法在编译时总是被认为是绑定的。
既然你问的是战略模式,我猜你有别的想法?如果你问是否可以在运行时选择"策略",你可以:
val op: (Int, Int) => Int =
if (args(0) == "+") add
else if (args(0) == "-") subtract
else multiply
execute(op, 3, 4)
在这种情况下,op
在运行时绑定到一个"策略"函数,但add
、subtract
和multiply
在编译时仍然绑定到它们的定义。
这是一个实现细节,这些方法中的每一个在编译时也与一个匿名Function2
类相关联,并且在运行时根据条件表达式的结果实例化适当的类。这个细节与绑定时间分析无关,因为add
、subtract
和multiply
标识符的含义在编译时是固定的。