1. Definition
The Mediator Design Pattern defines an object that encapsulates how a set of objects interact. It promotes loose coupling by keeping objects from referring to each other explicitly and allows their interaction to be centralized in the mediator.
2. Problem Statement
When you have a set of objects that need to communicate with one another, direct connections between them can lead to a system that's hard to understand, maintain, and change. The more each object knows about others, the more entangled they become, leading to a tightly-coupled system.
3. Solution
The Mediator Pattern suggests centralizing external communications between objects in a mediator object. This way, objects don't communicate directly with each other but instead go through the mediator. This reduces dependencies between collaborating objects, thereby decreasing coupling.
4. Real-World Use Cases
1. Air traffic control systems, where the control tower (mediator) ensures that planes don't collide.
2. Chat rooms, where the server (mediator) ensures the message gets to the right recipient.
3. GUI libraries, where components like buttons and text boxes communicate through a form (mediator).
5. Implementation Steps
1. Define a mediator interface that declares methods for communicating with colleagues.
2. Implement concrete mediators that coordinate how colleagues interact.
3. Define colleague classes that need to communicate with each other but do so through the mediator.
6. Implementation in Ruby
# Step 1: Mediator Interface
class Mediator
def notify(sender, event)
raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
end
end
# Step 2: Concrete Mediator
class ConcreteMediator < Mediator
def set_colleague1(colleague)
@colleague1 = colleague
end
def set_colleague2(colleague)
@colleague2 = colleague
end
def notify(sender, event)
if sender == @colleague1
@colleague2.react_to_event(event)
else
@colleague1.react_to_event(event)
end
end
end
# Step 3: Colleague Classes
class BaseColleague
def initialize(mediator)
@mediator = mediator
end
end
class Colleague1 < BaseColleague
def trigger_event
puts "Colleague1 triggers event"
@mediator.notify(self, :some_event)
end
def react_to_event(event)
puts "Colleague1 reacts to event"
end
end
class Colleague2 < BaseColleague
def trigger_event
puts "Colleague2 triggers event"
@mediator.notify(self, :some_event)
end
def react_to_event(event)
puts "Colleague2 reacts to event"
end
end
# Client Code
mediator = ConcreteMediator.new
colleague1 = Colleague1.new(mediator)
colleague2 = Colleague2.new(mediator)
mediator.set_colleague1(colleague1)
mediator.set_colleague2(colleague2)
colleague1.trigger_event
Output:
Colleague1 triggers event Colleague2 reacts to event
Explanation:
1. Mediator is an abstract class that defines the contract for concrete mediators.
2. ConcreteMediator knows about colleague classes and decides how one colleague reacts when an event occurs in another colleague.
3. BaseColleague is a base class for colleagues, and it holds a reference to a mediator.
4. Colleague1 and Colleague2 are concrete colleagues. They trigger events and react to events but communicate via the mediator.
5. In the client code, events are triggered in Colleague1, and as a result, Colleague2 reacts, demonstrating indirect communication through the mediator.
7. When to use?
Use the Mediator Pattern when:
1. You want to reduce the complexity of communication between objects.
2. You want to centralize external communications.
3. You want to encapsulate the way objects interact and work together in a separate mediator object.
Comments
Post a Comment