Skip to main content

Mediator: Coordination and Feedback

What this concept is​

Mediator owns interaction policy among participants. Participants report meaningful changes to the mediator rather than each knowing every other one. Observer is a notification mechanism; Mediator decides how collaborators react together. A mediator can use direct calls, Observer or a bus.

Why it matters here​

A form with country, delivery method and address widgets can develop a mesh of callbacks. A country change affects methods, which affects required address fields, which changes submit availability. Centralizing one workflow can make that policy testable, but a global mediator for unrelated workflows becomes a large hidden dependency.

Concrete example​

Use a pure coordination function for the smallest example:

def form_state(country, method, address):
available = ('pickup', 'post') if country == 'local' else ('post',)
selected = method if method in available else available[0]
needs_address = selected == 'post'
can_submit = not needs_address or bool(address.strip())
return available, selected, needs_address, can_submit

Inputs are strings and country is local or abroad. With (local,pickup,'') submit is enabled. Changing country to abroad normalizes method to post and disables submit until an address exists. The coordinator computes a whole consistent view before rendering it. Programmatic rendering must not create another user-change event loop. A real form also needs validation, labels, keyboard access and error feedback; this function supplies policy, not UI accessibility by itself.

Common confusion / misconception​

Mediator is not a synonym for event bus. Routing a message without interaction policy is merely dispatch. Moving every dependency into one object does not erase coupling. Bidirectional callbacks can still cycle through a mediator. Suppressing every repeated event can hide legitimate new input.

How to use it​

Scope one coordinator to one workflow lifetime. Distinguish user events from render updates, compute derived state once, then apply it. Define initialization, disposal and stale asynchronous response rules. Where policies are independent, keep them in small pure functions instead of growing one coordinator method.

Check yourself​

Who owns method normalization? Why should rendering not impersonate a user edit? What does disposal do to pending callbacks? Where does the interaction policy live if the same form is implemented without a mediator class?

Mini drill or application​

P19: enumerate the two countries, two methods and empty/nonempty address, checking all eight combinations. Draw three source events and two derived values. Add a delayed response with a generation number and show how a disposed or newer form rejects it. Review labels, focus order and announced errors on a real UI later.

Read this only if stuck​

GoF book index, 075-mediator-sample-code.md and 076-mediator-related-patterns.md. The local dialog example motivates coordination; this lesson's pure form model is newly authored.