What It Is
The Mediator pattern moves communication between many objects into one central place. Instead of everyone knowing everyone (and n objects meaning n·n connections), each object knows only the mediator, and the mediator routes.
Example: A Chat Room
Users never hold references to each other. A user sends to the room; the room delivers to everyone else. Joining and leaving touches one list, in one place.
Everyone talks through the room
Ana knows only the room; the room knows everyone. Delivery rules — skip the sender, later maybe mute or private messages — live in exactly one method.
Output: Go program and captured output
package main
import "fmt"
// The mediator: users never talk to each other directly.
type ChatRoom struct {
users []*User
}
func (c *ChatRoom) Join(u *User) {
u.room = c
c.users = append(c.users, u)
}
func (c *ChatRoom) Broadcast(from *User, msg string) {
for _, u := range c.users {
if u != from {
fmt.Println(u.name, "receives from", from.name+":", msg)
}
}
}
type User struct {
name string
room *ChatRoom
}
func (u *User) Send(msg string) {
u.room.Broadcast(u, msg)
}
func main() {
room := &ChatRoom{}
ana := &User{name: "ana"}
ben := &User{name: "ben"}
cleo := &User{name: "cleo"}
room.Join(ana)
room.Join(ben)
room.Join(cleo)
ana.Send("hello everyone")
}
When to Use It
Use it when many objects coordinate and the web of who-tells-whom is getting dense — chat systems, form fields that enable and disable each other, air-traffic-style coordination.
Skip it for two or three objects with simple links. A mediator between two parties is a middleman nobody hired.
Pros and Cons
Pros: participants stay simple and reusable; the coordination rules are readable in one place; adding a participant touches nothing else.
Cons: the mediator grows — it can quietly become the huge type that knows everything; all traffic through one point can hide performance costs.