Mat*_*ttK 12 design-patterns scala strategy-pattern
当我使用Java(或类似语言)编程时,我经常使用简单版本的策略模式,使用接口和实现类,在我的代码中提供特定概念的运行时可选实现.
作为一个非常人为的例子,我可能希望拥有一个可以在我的Java代码中产生噪音的Animal的一般概念,并希望能够在运行时选择动物的类型.所以我会沿着这些方向编写代码:
interface Animal {
void makeNoise();
}
class Cat extends Animal {
void makeNoise() { System.out.println("Meow"); }
}
class Dog extends Animal {
void makeNoise() { System.out.println("Woof"); }
}
class AnimalContainer {
Animal myAnimal;
AnimalContainer(String whichOne) {
if (whichOne.equals("Cat"))
myAnimal = new Cat();
else
myAnimal = new Dog();
}
void doAnimalStuff() {
...
// Time for the animal to make a noise
myAnimal.makeNoise();
...
}
Run Code Online (Sandbox Code Playgroud)
很简单.不过,最近,我一直在Scala开展一个项目,我想做同样的事情.使用特征这样做似乎很容易,例如:
trait Animal {
def makeNoise:Unit
}
class Cat extends Animal {
override def makeNoise:Unit = println("Meow")
}
class AnimalContainer {
val myAnimal:Animal = new Cat
...
}
Run Code Online (Sandbox Code Playgroud)
然而,这看起来非常类似Java而且不是很实用 - 更不用说特征和接口并不是真的相同.所以我想知道在我的Scala代码中是否有更惯用的方法来实现策略模式 - 或类似的东西 - 以便我可以在运行时选择抽象概念的具体实现.或者使用特征是实现这一目标的最佳方法?
Von*_*onC 12
它可能就像" scala中的设计模式 "中的那个例子:
就像任何函数是第一类对象或闭包可用的语言一样,策略模式很明显.
例如.考虑'征税'的例子:
trait TaxPayer
case class Employee(sal: Long) extends TaxPayer
case class NonProfitOrg(funds: BigInt) extends TaxPayer
//Consider a generic tax calculation function. (It can be in TaxPayer also).
def calculateTax[T <: TaxPayer](victim: T, taxingStrategy: (T => long)) = {
taxingStrategy(victim)
}
val employee = new Employee(1000)
//A strategy to calculate tax for employees
def empStrategy(e: Employee) = Math.ceil(e.sal * .3) toLong
calculateTax(employee, empStrategy)
val npo = new NonProfitOrg(100000000)
//The tax calculation strategy for npo is trivial, so we can inline it
calculateTax(nonProfit, ((t: TaxPayer) => 0)
Run Code Online (Sandbox Code Playgroud)
这样我就可以在运行时选择抽象概念的具体实现.
在这里,您使用上限,以便将子类中的T的特化限制为这些子类型TaxPayer.
你可以对蛋糕图案做一个变化.
trait Animal {
def makenoise: Unit
}
trait Cat extends Animal {
override def makeNoise { println("Meow") }
}
trait Dog extends Animal {
override def makeNoise { println("Woof") }
}
class AnimalContaineer {
self: Animal =>
def doAnimalStuff {
// ...
makeNoise
// ...
}
}
object StrategyExample extends Application {
val ex1 = new AnimalContainer with Dog
val ex2 = new AnimalContainer with Cat
ex1.doAnimalStuff
ex2.doAnimalStuff
}
Run Code Online (Sandbox Code Playgroud)
就策略模式而言,策略上的自我类型表明它必须与某种算法的特定实现混合在一起.
| 归档时间: |
|
| 查看次数: |
4229 次 |
| 最近记录: |