Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Mediator Pattern Medium

The mediator pattern defines an object that encapsulates how a set of objects interact. It promotes loose coupling by preventing objects from referring to each other directly, forcing them to communicate through the mediator instead.

Implementation

package mediator

import "fmt"

// Mediator defines the communication interface.
type Mediator interface {
	Notify(sender Component, event string)
}

// Component is the base for all participants.
type Component struct {
	mediator Mediator
}

func (c *Component) SetMediator(m Mediator) {
	c.mediator = m
}

// --- Concrete components ---

type AuthService struct{ Component }

func (a *AuthService) Login(user string) string {
	msg := fmt.Sprintf("%s logged in", user)
	a.mediator.Notify(a, "login")
	return msg
}

type Logger struct{ Component }

func (l *Logger) Log(message string) string {
	return fmt.Sprintf("LOG: %s", message)
}

type Notifier struct{ Component }

func (n *Notifier) Send(message string) string {
	return fmt.Sprintf("NOTIFY: %s", message)
}

// --- Concrete mediator ---

type AppMediator struct {
	auth     *AuthService
	logger   *Logger
	notifier *Notifier
}

func NewAppMediator() *AppMediator {
	m := &AppMediator{
		auth:     &AuthService{},
		logger:   &Logger{},
		notifier: &Notifier{},
	}
	m.auth.SetMediator(m)
	m.logger.SetMediator(m)
	m.notifier.SetMediator(m)
	return m
}

func (m *AppMediator) Notify(sender Component, event string) {
	switch event {
	case "login":
		m.logger.Log("user login event")
		m.notifier.Send("welcome back!")
	}
}

Usage

app := mediator.NewAppMediator()

fmt.Println(app.auth.Login("alice"))
// alice logged in
// (mediator also triggers logger and notifier behind the scenes)

Rules of Thumb

  • Use mediator when the communication logic between objects is complex and you want to centralize it in one place.
  • Mediator trades complexity in individual components for complexity in the mediator itself — avoid creating a “god object.”
  • In Go, channels can serve as a lightweight mediator between goroutines.