Flyweight Design Pattern in Scala

1. Definition

The Flyweight Design Pattern aims to minimize memory use by sharing as much data as possible with similar objects. It's a way to use objects in large numbers when a simple repeated representation would use an unacceptable amount of memory.

2. Problem Statement

Imagine needing to create a large number of similar objects, which could be resource-intensive, slowing down the application and consuming vast amounts of memory.

3. Solution

The solution is to create a shared pool of objects that can be reused instead of continuously creating new ones. The shared objects are known as 'flyweights'. They contain the shared data and delegate the non-shared parts to external data structures.

4. Real-World Use Cases

1. Representing characters in a word processor where each character is a flyweight with its graphical representation.

2. In gaming, where there might be many similar objects, like trees, buildings, etc., which can share common properties.

5. Implementation Steps

1. Identify the common data structure which can be shared among objects.

2. Create the Flyweight class containing this shared data.

3. Maintain a pool of these Flyweights to be reused when needed.

4. Ensure that the client code uses the Flyweight factory for object creation, and the factory reuses existing Flyweights or creates new ones as necessary.

6. Implementation in Scala Programming

// Flyweight class
class TreeType(val name: String, val color: String) {
  def display(x: Int, y: Int): Unit = println(s"Displaying $name tree of $color color at ($x,$y)")
}
// Flyweight Factory
object TreeFactory {
  private val treeTypes = scala.collection.mutable.Map[String, TreeType]()
  def getTreeType(name: String, color: String): TreeType = {
    treeTypes.getOrElseUpdate(name, new TreeType(name, color))
  }
}
// Client
object Forest extends App {
  val pineTree = TreeFactory.getTreeType("Pine", "Green")
  pineTree.display(1, 1)
  val anotherPineTree = TreeFactory.getTreeType("Pine", "Green")
  anotherPineTree.display(2, 2)
}

Output:

Displaying Pine tree of Green color at (1,1)
Displaying Pine tree of Green color at (2,2)

Explanation:

1. The TreeType class is our Flyweight, which contains shared data like 'name' and 'color'.

2. The TreeFactory maintains a pool of these tree types and serves requests to either create a new tree type or return an existing one.

3. In the client code, even though we request the 'Pine' tree type twice, the factory reuses the same object for both, saving memory.

4. The display function demonstrates how a shared object can be used in different contexts.

7. When to use?

Use the Flyweight pattern when:

1. A large number of objects needs to be created, and they share a lot of information.

2. Due to the vast amount of objects, storage costs are high.

3. Most of the object state can be extrinsic (i.e., external and can be computed on the fly).


Comments