Scala Tutorial - Traits, Companion Object, Factory Pattern

By Nadim Bahadoor | Last updated: February 12, 2020 at 13:07 pm

Overview

In this tutorial, we will learn how to use traits and companion objects to implement a Factory Pattern.

 

We will build on what we have learned from the previous tutorials:

Steps

1. Define a wrapper object called Cakes to hold various types of cakes

We will start by creating an object named Cakes as a convenient way to hold various kinds of cakes (see Step 1 in code snippet below).

 

Next, we define a trait name Cake which will expose the methods for a Cake. In our simple example, each Cake will have a method called name which returns a type of String (see Step 2 in code snippet below).

 

With the Cake trait defined, we can extend it to create various types of cakes. In the example below, we've defined a Cupcake, Donut and UnknownCake classes which extend the Cake trait (see Step 3 in code snippet below).


// Step 1: Define a wrapper object called Cakes to hold various types of cakes
object Cakes {

 // Step 2: Define a base trait to represent a Cake
 trait Cake {
   def name: String
 }

 // Step 3: Define class implementations for the Cake trait namely: Cupcake, Donut and UnknownCake
 class UnknownCake extends Cake {
   override def name: String = "Unknown Cake ... but still delicious!"
 }

 class Cupcake extends Cake {
   override def name: String = "Cupcake"
  }

 class Donut extends Cake {
   override def name: String = "Donut"
  }

 }

NOTE:

2. Define another object with an apply() method as factory for types of cakes

We create another object named CakeFactory and it will be a convenient wrapper for our factory pattern (see Step 4 in code snippet below).

 

Finally, we defined an apply() method which will Pattern Match on String and return an actual corresponding Cake implementation (see Step 5 in code snippet below).


// Step 4: Define a wrapper object called CakeFactory")
object CakeFactory {
 import Cakes._

 // Step 5: Define an apply method which will act as a factory to produce the correct Cake implementation
 def apply(cake: String): Cake = {
   cake match {
    case "cupcake" => new Cupcake
    case "donut" => new Donut
    case _ => new UnknownCake
   }
  }
 }

NOTE:

  • In a real application, you would perhaps want to control the types of cakes and pattern match on an enum as opposed to a String. In upcoming tutorial, I will show you how to use sealed traits to define enum.

3. Call the CakeFactory

Calling the CakeFactory is pretty easy by simply passing a String type as defined in the apply method from Step 2.


// Step 6: Call the CakeFactory
println(s"A cupcake = ${CakeFactory("cupcake").name}")
println(s"A donut = ${CakeFactory("donut").name}")
println(s"Unknown cake = ${CakeFactory("coconut tart").name}")

You should see the following output when you run your Scala application in IntelliJ:


A cupcake = Cupcake
A donut = Donut
Unknown cake = Unknown Cake ... but still delicious!

 

This concludes our tutorial on Traits, Companion Object, Factory Pattern and I hope you've found it useful!

 

Stay in touch via Facebook and Twitter for upcoming tutorials!

 

Don't forget to like and share this page :)

Summary

In this tutorial, we went over the following:

  • Define a wrapper object called Cakes to hold various types of cakes
  • Define another object with an apply() method as factory for types of cakes
  • Call the CakeFactory

Tip

  • We've kept the trait type parameters example simple but it would be good to review variance namely covariance and contra-variance type parameters.
  • In upcoming tutorials in this Chapter, we will also show how to use traits to build some pure Functional Programming constructs such as Monoids and Functors and much more!

Source Code

The source code is available on the allaboutscala GitHub repository.

 

What's Next

In the next tutorial, I will show you how to use a Type Class for ad-hoc polymorphism.

Nadim Bahadoor on FacebookNadim Bahadoor on GithubNadim Bahadoor on LinkedinNadim Bahadoor on Twitter
Nadim Bahadoor
Technology and Finance Consultant with over 14 years of hands-on experience building large scale systems in the Financial (Electronic Trading Platforms), Risk, Insurance and Life Science sectors. I am self-driven and passionate about Finance, Distributed Systems, Functional Programming, Big Data, Semantic Data (Graph) and Machine Learning.
Other allaboutscala.com tutorials you may like: