Use when many objects communicate with each other in complex, tangled ways — centralizing all interaction in a mediator object so that components only talk to the mediator, not to each other.
Scanned 9/8/2026
Install to Claude Code
npx -y skills add jeffreytse/grimoire-core --skill apply-mediator-pattern --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Apply Mediator Pattern?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/jeffreytse-apply-mediator-pattern)More formats (shields.io, HTML) on the badges page.
---
name: apply-mediator-pattern
description: Use when many objects communicate with each other in complex, tangled ways — centralizing all interaction in a mediator object so that components only talk to the mediator, not to each other.
source: 'Gamma, Helm, Johnson, Vlissides, "Design Patterns: Elements of Reusable Object-Oriented Software" (1994) pp. 273–282; chat room servers; aviation air traffic control; React event handling architecture; MediatR library (.NET)'
tags: [design-patterns, behavioral, mediator, oop, developer, decoupling, event-coordination]
related: [apply-observer-pattern, apply-facade-pattern, apply-low-coupling]
---
# Apply Mediator Pattern
Define an object that encapsulates how a set of objects interact, promoting loose coupling by preventing direct object-to-object references.
## Why This Is Best Practice
**Adopted by:** MediatR (.NET) — used in the majority of .NET CQRS implementations,
downloaded 100M+ times on NuGet — is a direct implementation of the Mediator pattern.
React's unidirectional data flow (state lifted to parent components that coordinate
children) applies Mediator at the UI level. Message brokers (Kafka, RabbitMQ) are
infrastructure-level mediators — adopted by virtually every large-scale distributed system.
**Impact:** GoF documents that M objects with direct references to each other require
M×(M-1) connection points. With a mediator, each of M objects has one reference (to
the mediator): M connections total. Changing one component's interaction requires
modifying one method in the mediator — not M-1 classes.
**Why best:** Direct object-to-object communication — the alternative — creates a web
of dependencies where a change to one component's protocol cascades to all its direct
communicators. Mediator centralizes that protocol and isolates changes.
Sources: Gamma et al. (1994) pp. 273–282; MediatR documentation (.NET);
React "lifting state up" documentation
## Steps
### Step 1: Define the mediator interface
```python
from abc import ABC, abstractmethod
class ChatMediator(ABC):
@abstractmethod
def send_message(self, message: str, sender: "ChatUser") -> None: ...
@abstractmethod
def add_user(self, user: "ChatUser") -> None: ...
```
### Step 2: Implement the concrete mediator — coordinates component interactions
```python
class ChatRoom(ChatMediator):
def __init__(self):
self._users: list["ChatUser"] = []
def add_user(self, user: "ChatUser") -> None:
self._users.append(user)
def send_message(self, message: str, sender: "ChatUser") -> None:
for user in self._users:
if user is not sender:
user.receive(message, sender.name)
```
### Step 3: Define the colleague (component) — knows only the mediator
```python
class ChatUser:
def __init__(self, name: str, mediator: ChatMediator):
self.name = name
self._mediator = mediator
def send(self, message: str) -> None:
print(f"{self.name} sends: {message}")
self._mediator.send_message(message, self) # talks to mediator, not other users
def receive(self, message: str, from_name: str) -> None:
print(f"{self.name} receives from {from_name}: {message}")
```
### Step 4: Wire up via the mediator — components never reference each other
```python
room = ChatRoom()
alice = ChatUser("Alice", room)
bob = ChatUser("Bob", room)
carol = ChatUser("Carol", room)
room.add_user(alice)
room.add_user(bob)
room.add_user(carol)
alice.send("Hello everyone!") # Bob and Carol receive — Alice never references them
```
### Step 5: Add coordination logic to the mediator — not to components
If sending a message should log, filter profanity, or throttle, that logic belongs in
`ChatRoom.send_message()` — not in each `ChatUser.send()`. Components stay simple;
the mediator handles coordination.
## When NOT to Use
- **When only 2–3 objects interact** — for a small, stable set of direct collaborators, a mediator adds indirection without payoff. Use direct references.
- **When the mediator becomes a God Object** — if the mediator contains complex business logic for many unrelated interactions, it's an anti-pattern. Split into multiple focused mediators.
## Common Mistakes
**Mediator that leaks component knowledge.** If the mediator imports concrete component types and calls their specific methods, it's tightly coupled to every component it coordinates. Use the component interface, not concrete types.
**Components calling each other through the mediator inefficiently.** If A needs a response from B synchronously, a mediator round-trip adds latency. Direct synchronous calls may be appropriate for tightly-coupled pairs.
**Confusing Mediator with Facade.** Facade simplifies a subsystem for external clients. Mediator coordinates internal communication between components in the same subsystem. Components don't know about a Facade; they do know about the Mediator.Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!