Better alternative to Strategy pattern in Scala?

When I’m programming in Java (or a similar language), I often employ a simple version of the Strategy pattern, using interfaces and implementation classes, to provide runtime-selectable implementations of a particular concept in my code.

As a very contrived example, I might want to have the general concept of an Animal that can make a noise in my Java code, and want to be able to select the type of animal at runtime. So I would write code along these lines:

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();
        ...
    }

Simple enough. Recently, though, I’ve been working on a project in Scala and I want to do the same thing. It seems easy enough to do this using traits, with something like this:

trait Animal {
    def makeNoise:Unit
}

class Cat extends Animal {
    override def makeNoise:Unit = println("Meow")
}

class AnimalContainer {
    val myAnimal:Animal = new Cat
    ...
}

However, this seems very Java-like and not very functional–not to mention that traits and interfaces aren’t really the same thing. So I’m wondering if there’s a more idiomatic way to implement the Strategy pattern–or something like it–in my Scala code so that I can select a concrete implementation of an abstract concept at runtime. Or is using traits the best way to achieve this?

Answer

It could go like that example in “Design pattern in scala“:

Like any language where functions are first-class objects or where closures are available, Strategy pattern is obvious.
For eg. consider the ‘taxing’ example:

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)

so that I can select a concrete implementation of an abstract concept at runtime.

Here you are using an upper bound in order to restricts the specializations of T in subclasses to those subtypes of TaxPayer.

Attribution
Source : Link , Question Author : MattK , Answer Author : Community

Leave a Comment