Mediator Pattern in Ruby: Simplifying Object Interactions

Explore the Mediator Pattern in Ruby, a behavioral design pattern that simplifies object interactions by encapsulating communication logic within a mediator. Learn how to implement this pattern to enhance maintainability and reduce dependencies.

6.5 Mediator Pattern

In the realm of software design, managing complex interactions between objects can become a daunting task. The Mediator pattern offers a solution by encapsulating these interactions within a single object, known as the mediator. This pattern promotes loose coupling and enhances maintainability by preventing objects from referring to each other explicitly.

Intent of the Mediator Pattern

The primary intent of the Mediator pattern is to define an object that encapsulates how a set of objects interact. By centralizing communication logic, the pattern reduces dependencies between communicating objects, making the system easier to understand and modify.

Problem Addressed by the Mediator Pattern

In complex systems, objects often need to communicate with each other. Without a mediator, each object would need to know about the others, leading to a tightly coupled system. This tight coupling makes the system difficult to maintain and extend. The Mediator pattern addresses this problem by introducing a mediator object that handles all communication between objects, thereby reducing their dependencies on one another.

Key Participants

  1. Mediator: Defines an interface for communicating with Colleague objects.
  2. ConcreteMediator: Implements cooperative behavior by coordinating Colleague objects.
  3. Colleague: Each Colleague class knows its Mediator object and communicates with it whenever it would have otherwise communicated with another Colleague.

Applicability

Use the Mediator pattern when:

  • A set of objects communicate in well-defined but complex ways.
  • Reusing an object is difficult because it refers to and communicates with many other objects.
  • A behavior that’s distributed between several classes should be customizable without a lot of subclassing.

Implementing the Mediator Pattern in Ruby

Let’s explore how to implement the Mediator pattern in Ruby with a practical example. We’ll create a simple chat room application where users can send messages to each other through a mediator.

Step 1: Define the Mediator Interface

First, we define an interface for the mediator. In Ruby, we can use a module to define this interface.

1module ChatMediator
2  def send_message(message, user)
3    raise NotImplementedError, 'This method should be overridden in a subclass'
4  end
5end

Step 2: Implement the ConcreteMediator

Next, we implement the ConcreteMediator class, which will handle the communication between users.

 1class ChatRoom
 2  include ChatMediator
 3
 4  def initialize
 5    @users = []
 6  end
 7
 8  def add_user(user)
 9    @users << user
10  end
11
12  def send_message(message, user)
13    @users.each do |u|
14      u.receive_message(message) unless u == user
15    end
16  end
17end

Step 3: Define the Colleague Class

Now, let’s define the User class, which will act as a colleague in our pattern.

 1class User
 2  attr_reader :name
 3
 4  def initialize(name, chat_room)
 5    @name = name
 6    @chat_room = chat_room
 7    @chat_room.add_user(self)
 8  end
 9
10  def send_message(message)
11    puts "#{@name} sends: #{message}"
12    @chat_room.send_message(message, self)
13  end
14
15  def receive_message(message)
16    puts "#{@name} receives: #{message}"
17  end
18end

Step 4: Demonstrate the Mediator Pattern

Let’s see how the mediator pattern works in action.

 1# Create a chat room (mediator)
 2chat_room = ChatRoom.new
 3
 4# Create users (colleagues)
 5alice = User.new('Alice', chat_room)
 6bob = User.new('Bob', chat_room)
 7charlie = User.new('Charlie', chat_room)
 8
 9# Users send messages through the mediator
10alice.send_message('Hello, everyone!')
11bob.send_message('Hi, Alice!')
12charlie.send_message('Hey, folks!')

Benefits of the Mediator Pattern

  • Simplified Object Interactions: By centralizing communication logic, the Mediator pattern simplifies interactions between objects.
  • Enhanced Maintainability: With reduced dependencies, the system becomes easier to maintain and extend.
  • Improved Reusability: Objects can be reused more easily since they are decoupled from each other.

Design Considerations

  • Single Point of Failure: The mediator can become a single point of failure if not designed carefully.
  • Complexity: While the mediator simplifies object interactions, it can introduce complexity if it becomes too large.

Ruby Unique Features

Ruby’s dynamic nature and metaprogramming capabilities can be leveraged to create flexible and powerful mediator implementations. For instance, you can dynamically define methods in the mediator to handle different types of messages.

Differences and Similarities

The Mediator pattern is often confused with the Observer pattern. While both patterns decouple objects, the Mediator pattern centralizes communication, whereas the Observer pattern allows objects to subscribe to events.

Try It Yourself

Experiment with the code by adding more users or modifying the message format. Try implementing additional features, such as private messaging or user status notifications.

 1# Add a private message feature
 2class ChatRoom
 3  # Existing code...
 4
 5  def send_private_message(message, sender, receiver)
 6    receiver.receive_message("Private from #{sender.name}: #{message}")
 7  end
 8end
 9
10# Usage
11chat_room.send_private_message('This is a secret!', alice, bob)

Visualizing the Mediator Pattern

    classDiagram
	    class ChatMediator {
	        +send_message(message, user)
	    }
	    class ChatRoom {
	        +add_user(user)
	        +send_message(message, user)
	    }
	    class User {
	        +send_message(message)
	        +receive_message(message)
	    }
	    ChatMediator <|-- ChatRoom
	    ChatRoom o-- User

The diagram above illustrates the relationship between the ChatMediator, ChatRoom, and User classes. The ChatRoom acts as the mediator, coordinating communication between User instances.

Knowledge Check

  • What is the primary intent of the Mediator pattern?
  • How does the Mediator pattern reduce dependencies between objects?
  • What are some potential drawbacks of using the Mediator pattern?

Summary

The Mediator pattern is a powerful tool for managing complex interactions between objects. By encapsulating communication logic within a mediator, it promotes loose coupling and enhances maintainability. As you continue to explore design patterns, consider how the Mediator pattern can simplify your application’s architecture.

Remember, this is just the beginning. As you progress, you’ll build more complex and interactive applications. Keep experimenting, stay curious, and enjoy the journey!

Quiz: Mediator Pattern

Loading quiz…
Revised on Thursday, April 23, 2026