Adapter Design Pattern in Scala

1. Definition

The Adapter Design Pattern allows objects with incompatible interfaces to work together. It acts as a bridge between two incompatible interfaces by providing a compatible interface that forwards calls to one of the encapsulated objects.

2. Problem Statement

You have two incompatible interfaces, and you need to allow them to work together, but you cannot modify the existing code of these interfaces.

3. Solution

The Adapter pattern suggests that you create a new adapter class with an interface that you need and then delegate all the calls inside these methods to the service object methods you already have.

4. Real-World Use Cases

1. Translating one API to another so that it aligns with a different system.

2. Allowing software to interface with third-party or legacy code that wouldn't be possible with the software's current interface.

5. Implementation Steps

1. Identify the two existing interfaces that are not compatible.

2. Create an Adapter class that joins functionalities of independent or incompatible interfaces.

3. Create a method in the Adapter that is compatible with one of the interfaces and delegates the call to the other incompatible interface.

6. Implementation in Scala Programming

// Step 1: Define the existing interfaces
trait OldSystem {
  def oldRequest(): String
}
class OldServiceImpl extends OldSystem {
  def oldRequest(): String = "Old system in action"
}
trait NewSystem {
  def newRequest(): String
}
// Step 2: Create the Adapter class
class Adapter(oldSystem: OldSystem) extends NewSystem {
  def newRequest(): String = oldSystem.oldRequest()
}
// Step 3: Client code
object Main extends App {
  val oldService = new OldServiceImpl
  val adapter = new Adapter(oldService)
  println(adapter.newRequest())
}

Output:

Old system in action

Explanation:

1. We start with two incompatible interfaces: OldSystem and NewSystem.

2. The Adapter class provides a compatible interface by extending NewSystem and contains an instance of the OldSystem.

3. Within the newRequest method of the Adapter, it delegates the call to the oldRequest method of the OldSystem.

4. The client code can now use the NewSystem interface and internally call methods from the OldSystem.

7. When to use?

The Adapter pattern is beneficial when:

1. You need to use existing classes, but their interfaces aren't compatible with the rest of your code.

2. You want to create a reusable class that cooperates with unrelated or unforeseen classes.

3. You need to create a class for converting various data types to other data types without changing the data source.


Comments