A Scala Factory Pattern example

Here’s a small example of how to create a Factory Pattern in Scala. In the Scala Cookbook I created what some people might call a simple factory and/or static factory, so the following code is a much better implementation of a true OOP Factory Pattern.

My Scala factory classes

I don’t have too much time to explain the code today, but here are the classes that make up my Scala factory, including a set of “animal” classes along with a DogFactory and CatFactory that extend an AnimalFactory trait:

package animals {

    // --------------
    // Animal classes
    // --------------
    sealed trait Animal {
        def speak: Unit
    }

    sealed trait Dog extends Animal
    private class LittleDog extends Dog  { def speak = println("arf")   }
    private class GenericDog extends Dog { def speak = println("woof")  }
    private class BigDog extends Dog     { def speak = println("WOOF!") }

    sealed trait Cat extends Animal
    private class GenericCat extends Cat { def speak = println("meow")    }
    private class GrumpyCat extends Cat  { def speak = println(":(")      }
    private class SmellyCat extends Cat  { def speak = println("..oOo..") }


    // ---------------------
    // AnimalFactory classes
    // ---------------------
    trait AnimalFactory {
        def getAnimal(criteria: String): Animal
    }

    class DogFactory extends AnimalFactory {
        def getAnimal(criteria: String): Animal = criteria match {
            case "small" | "little" => new LittleDog
            case "big" | "large" => new BigDog
            case _ => new GenericDog
        }
    }

    class CatFactory extends AnimalFactory {
        def getAnimal(criteria: String) = criteria match {
            case "smells" | "smelly" => new SmellyCat
            case "grumpy" => new GrumpyCat
            case _ => new GenericCat
        }
    }
}

Note that unlike what I did in the Cookbook, I don’t use object here; everything is implemented with traits and classes.

Testing the factory

Next, here’s an App I used to test the factory, including making sure I could access all of the concrete Dog and Cat classes:

/**
 * i put this code in another package to confirm that i can
 * use the Dog and Cat classes.
 */
package factory_pattern {

    import animals._

    object FactoryPattern extends App {

        val dogFactory: AnimalFactory = new DogFactory
        val catFactory: AnimalFactory = new CatFactory

        println("=== SOME DOGS ===")
        val smallDog = dogFactory.getAnimal("small")
        val bigDog = dogFactory.getAnimal("big")
        val dog = dogFactory.getAnimal("other")    
        smallDog.speak
        bigDog.speak
        dog.speak

        println("=== SOME CATS ===")
        (catFactory.getAnimal("smells")).speak
        (catFactory.getAnimal("grumpy")).speak
        (catFactory.getAnimal("regular")).speak

    }
}