Skip to main content

Code example of the Factory Pattern example in Scala

The Factory Pattern is a creational design pattern for creating objects that share a common superclass.

This pattern allows you to decouple the creator of the class from the classes that you need to create. It allows you to simplify the object creation and move all that logic into a single place, so it becomes easier to test and maintain.

In this page, you’ll find an example of the Factory Pattern in Scala.

Output of the factory

In order to use the factory pattern, we need to define an abstract class that needs to be extended by the classes we want to create on the factory. This abstract class is like a template that will be used to create the objects.

abstract class Monster {

val healthPoints: Int
val attackPoints: Int

}

class Slime extends Monster {
override val healthPoints: Int = 1
override val attackPoints: Int = 1

override def toString: String = s"Slime: HP ${healthPoints} - Attack: ${attackPoints}"
}

class Troll extends Monster {

override val healthPoints: Int = 10
override val attackPoints: Int = 20

override def toString: String = s"Troll: HP ${healthPoints} - Attack: ${attackPoints}"
}

The factory class

The key points of the Factory are:

  • It will have a “create” method that will pass the information needed to create the object that we want.
  • It will return an object of the abstract class we have defined earlier.
  • It can be either a class or an object, depending on if we need some state to configure it.
class MonsterFactory {  // object MonsterFactory

def createMonster(monsterType: String): Monster = {
monsterType match {
case "slime" => new Slime()
case "troll" => new Troll()
case _ => throw new Exception("Monster type not recognized.")
}
}

How to use it

To use the factory that we have created, simply create an instance and invoke the “create” method with the output that you need.

object Main {

def main(args: Array[String]): Unit = {

// Create factory
val monsterFactory = new MonsterFactory()

// Create instances of different monsters
val m1 = monsterFactory.createMonster("slime")
println(m1)

val m2 = monsterFactory.createMonster("troll")
println(m2)
}
}
--- Output
>> Slime: HP 1 - Attack: 1
>> Troll: HP 10 - Attack: 20

This pattern can be specially useful in your data pipelines, as it allows you can have a Factory that creates different data pipelines depending on the input arguments, so if you have different classes that represent your data pipelines, you can dynamically instantiate the one that you need.