Mediator Design Pattern in R

1. Definition

The Mediator Design Pattern defines an object that encapsulates how a set of objects interact. This pattern promotes loose coupling by keeping objects from referring to each other explicitly, and it allows their interaction to vary independently.

2. Problem Statement

Consider multiple components in a system that need to communicate with each other. Direct communication between these components makes them tightly coupled. This tight coupling causes changes in one component to affect others, making the system rigid and hard to maintain.

3. Solution

Introduce a mediator object that centralizes external communications between components. Instead of components communicating directly with each other, they communicate through the mediator. This approach decouples components, making the system more flexible and easier to maintain.

4. Real-World Use Cases

1. Air traffic control tower directing the takeoff and landing of planes.

2. Chat room where participants send messages to the chat room, and the chat room then broadcasts the message to all participants.

3. Graphical user interfaces where a mediator handles events and dispatches them to appropriate components.

5. Implementation Steps

1. Define the Mediator interface that will encapsulate interactions between Colleague objects.

2. Create ConcreteMediator that implements the Mediator interface.

3. Create Colleague classes that will communicate through the Mediator.

6. Implementation in R Programming

# Step 1: Mediator Interface
Mediator <- setRefClass("Mediator", methods = list(
  send_message = function(message, colleague) {}
))
# Step 2: ConcreteMediator
ConcreteMediator <- setRefClass("ConcreteMediator", contains = "Mediator",
  fields = list(colleague1 = "Colleague", colleague2 = "Colleague"),
  methods = list(
    send_message = function(message, colleague) {
      if (identical(colleague, colleague1)) {
        colleague2$receive(message)
      } else {
        colleague1$receive(message)
      }
    }
  )
)
# Step 3: Colleague Class
Colleague <- setRefClass("Colleague",
  fields = list(mediator = "Mediator"),
  methods = list(
    send = function(message) {
      mediator$send_message(message, .self)
    },
    receive = function(message) {
      cat("Message received:", message, "\n")
    }
  )
)
# Client Code
mediator <- ConcreteMediator$new()
colleague1 <- Colleague$new(mediator = mediator)
colleague2 <- Colleague$new(mediator = mediator)
mediator$colleague1 <- colleague1
mediator$colleague2 <- colleague2
colleague1$send("Hello from Colleague 1!")
colleague2$send("Hi there, Colleague 1!")

Output:

Message received: Hello from Colleague 1!
Message received: Hi there, Colleague 1!

Explanation:

1. The Mediator interface defines a method for sending messages.

2. ConcreteMediator is a concrete implementation of the Mediator, which knows how to route messages between colleagues.

3. Colleague represents components that need to communicate with each other. They send and receive messages via the mediator.

4. In the client code, two colleagues communicate by sending messages, but they don't send messages directly to each other. Instead, they use the mediator, which handles the message routing.

7. When to use?

Use the Mediator Design Pattern when:

1. You want to reduce subclassing by not having components reference each other directly.

2. You want to decouple many-to-many relationships between communicating objects to one-to-many relationships.

3. You want to encapsulate the interactions between objects in a single location, simplifying maintenance and evolution.

The Mediator pattern centralizes external communications, which can help ensure that components behave consistently.


Comments