Skip to main content

🧩 Observer × Mediator

✅ Combination Intent

  • Use Observer to decouple event emitters from event listeners
  • Use Mediator to centralize control over notification flow

This combination allows you to emit events without knowing who will respond, manage notification targets in one place, and dynamically add/remove observers without modifying the source.

✅ Common Use Cases

  • When you need to perform multiple actions (e.g., email, logging, Slack notifications) after user registration or form submission
  • When the post-processing steps may change or increase in the future
  • When decoupling the sender and listeners improves testability and flexibility

✅ UML Class Diagram

✅ Code Example

// Observer インターフェース
interface Observer {
update(event: string, data: any): void;
}

// Mediator インターフェース
interface Mediator {
notify(sender: string, event: string, data: any): void;
}

// 実際の Mediator
class EventHub implements Mediator {
private observers: Observer[] = [];

addObserver(observer: Observer): void {
this.observers.push(observer);
}

notify(sender: string, event: string, data: any): void {
for (const obs of this.observers) {
obs.update(event, data);
}
}
}

// イベント発生元(Subject)
class UserService {
constructor(private mediator: Mediator) {}

registerUser(name: string): void {
console.log(`Registering user: ${name}`);
this.mediator.notify("UserService", "user_registered", { name });
}
}

// 通知を受け取る Observer
class Mailer implements Observer {
update(event: string, data: any): void {
if (event === "user_registered") {
console.log(`[Mailer] Sending welcome email to ${data.name}`);
}
}
}

class Logger implements Observer {
update(event: string, data: any): void {
console.log(`[Logger] Event: ${event}, Data: ${JSON.stringify(data)}`);
}
}

// 使用例
const mediator = new EventHub();
const mailer = new Mailer();
const logger = new Logger();
mediator.addObserver(mailer);
mediator.addObserver(logger);

const userService = new UserService(mediator);
userService.registerUser("Taro");

✅ Explanation

  • Observer defines the update() method that responds to events
  • Mediator (via EventHub) manages how events are broadcast to observers
  • UserService only calls notify() on the mediator, unaware of the actual event handlers
  • Mailer and Logger are Observer implementations that respond independently to events

This design enables loose coupling between emitters and listeners, while also allowing centralized and transparent control of notification behavior.

✅ Summary

  • Observer enables event-driven design with flexible listeners
  • Mediator centralizes event flow and observer management
  • Ideal for event-driven systems that require scalability, testability, and modular post-processing