Factory Method Design Pattern in Scala

1. Definition

The Factory Method Design Pattern is a creational pattern that provides an interface for creating objects in a super class, but allows subclasses to alter the type of objects that will be created.

2. Problem Statement

In software development, we might need to instantiate one of several subclasses, but the exact subclass might not be known until runtime. Hard-coding the instantiation of specific classes can reduce code flexibility and increase coupling.

3. Solution

The Factory Method pattern suggests defining a method for creating objects in a super class and letting the subclasses decide which class to instantiate. The Factory Method is usually defined in an interface, which is implemented by concrete classes.

4. Real-World Use Cases

1. GUI libraries where each OS provides a different implementation of a button or a window.

2. Payment gateway integration where the method of payment (credit card, PayPal, etc.) determines the type of payment object instantiated.

5. Implementation Steps

1. Define an interface or an abstract class with a factory method.

2. Concrete classes will implement this interface or extend this abstract class and override the factory method.

6. Implementation in Scala Programming

// Abstract class with the factory method
abstract class Product {
  def description: String
}
abstract class Creator {
  def createProduct(): Product
}
class ConcreteProductA extends Product {
  override def description: String = "Product A"
}
class ConcreteProductB extends Product {
  override def description: String = "Product B"
}
class ConcreteCreatorA extends Creator {
  override def createProduct(): Product = new ConcreteProductA()
}
class ConcreteCreatorB extends Creator {
  override def createProduct(): Product = new ConcreteProductB()
}
// Client code
object Main extends App {
  val creatorA: Creator = new ConcreteCreatorA()
  val productA: Product = creatorA.createProduct()
  println(productA.description)
  val creatorB: Creator = new ConcreteCreatorB()
  val productB: Product = creatorB.createProduct()
  println(productB.description)
}

Output:

Product A
Product B

Explanation:

1. We have an abstract class Product that serves as the base for our products.

2. Creator is an abstract class with a factory method createProduct.

3. ConcreteProductA and ConcreteProductB are concrete implementations of Product.

4. ConcreteCreatorA and ConcreteCreatorB are concrete creators that implement the factory method to produce respective products.

5. In the client code, we demonstrate creating products using the factory methods of the respective creators.

7. When to use?

The Factory Method pattern is useful when:

1. A class can't anticipate the type of objects it needs to create.

2. A class wants its subclasses to specify the objects it creates.

3. Classes delegate responsibility to one of several helper subclasses, and you want to localize the knowledge of which helper subclass is the delegate.

Remember, the main intent of this pattern is to define an interface for creating an object, but let the subclasses decide which class to instantiate.


Comments