Strategy Pattern in Scala

Saurabh Kishore Tiwari
The Thought Mill
4 min readMay 7, 2023

--

Are you tired of your codebase resembling a game of jenga, where pulling one block out can cause everything to come crashing down? Fear not, my friend, for there’s a design pattern that can save the day — the Strategy Pattern!

Think of it like this: your code is a toddler who needs guidance and structure to behave properly. And just like a toddler, your code can throw tantrums and act up when it doesn’t get its way. But with the Strategy pattern, you can give your code a clear set of rules to follow and avoid those pesky temper tantrums.

So get ready to be the ultimate code parent and teach your program some manners with the Strategy pattern. Who knows, maybe your code will even start saying “please” and “thank you” in no time.

Without wasting much time, let’s see the UML Diagram:

Let’s breakdown the structure now

Strategy
1. Declares an interface common to all supported algorithms. Context uses this interface to call the algorithm defined by a ConcreteStrategy.

ConcreteStrategy
1. Implements the algorithm using the Strategy interface.

Context
1. Configured with a ConcreteStrategy Object.
2. Maintains a reference to a Strategy Object.
3. May define an interface that lets Strategy access its data.

Implementation

Imagine 2 types of ducks. A Mallard Duck and a Wooden Duck(who said it has to be a live duck 😏). Now, focus on two properties of a duck, Flying and Quacking.

Malard Duck — Normal Fly and Quack
Wooden Duck — No Fly and No Quack

Hmmm, till now, we can have 2 classes, one for each duck type and write the fly and quack methods for them because they are unique. Very simple right? But who wants it simple? A wise person once said — “I don’t want peace, I want problems, always!”

Now, let’s introduce a new Duck type — Model Duck. This Duck flies but does not quack. Still, we can have 3 different classes and manage them. Now, one more duck enters the picture, A Rubber Duck. It does not fly but quacks.

I think you can guess the pattern by now, a new duck enters the room and has its own flying and quacking behavior.

There are many sorting algorithms available but their end result is the same. You can create an interface Sort and a class for each sorting algorithm and all of them implement Sort.

So, let FlyingBehavior and QuackingBehavior be two different interfaces and we can have multiple classes inheriting these behaviors and having an implementation.

Question — Will it be better to use inheritance in this case or composition?
Answer — I think it’s a personal choice. I always do it this way… which sounds better? “has a” or “is a”?
Like, Car “is a” vehicle and Car “has a” steering wheel. This helps with the clarity I need in my life 😌. This also helps with keeping me away from “Class Explosion”

UML for our implementation might look like:

Now, just to be clear, your implementation might differ a bit. You may bring in a DuckName interface to deal with a new duck everytime. Just make sure, you’re using composition over inheritance in this case.

Code

DuckBehaviors.scala

//Fly Behaviors for Duck
trait FlyBehavior:
def fly(): String

object SimpleFlying extends FlyBehavior:
override def fly(): String = "I simply fly"

object NoFlying extends FlyBehavior:
override def fly(): String = "I don not fly"

//Quack Behaviors for the Duck
trait QuackBehavior:
def quack(): String

object SimpleQuacking extends QuackBehavior:
override def quack(): String = "I make quacking sound - quack-quack!"

object NoQuacking extends QuackBehavior:
override def quack(): String = "I do not quack"

Duck.scala

class Duck (name: String,
flyBehavior: FlyBehavior,
quackBehavior: QuackBehavior):
def display(): String = s"I am a $name. ${flyBehavior.fly()}. ${quackBehavior.quack()}"

MainRunner.scala

object MainRunner extends App:
private val mallardDuck = Duck("Mallard Duck", SimpleFlying, SimpleQuacking)
private val woodenDuck = Duck("Wooden Duck", NoFlying, NoQuacking)

println(mallardDuck.display())
println(woodenDuck.display())

Output

I am a Mallard Duck. I simply fly. I make quacking sound - quack-quack!
I am a Wooden Duck. I don not fly. I do not quack

Known Uses and Related Patterns

Strategy Pattern is one of the most widely used design pattern. We can implement in the following cases:

  • Different variations of an algorithm are needed.
  • The client does not need to know the algorithm.
  • The algorithm should be exchangeable at the run time of a program.

--

--