Najkrócej: Mediator porządkuje komunikację i ogranicza chaos zależności
- Wzorzec przenosi decyzję o tym, kto z kim i kiedy rozmawia, do jednego obiektu pośredniczącego.
- Najbardziej pomaga tam, gdzie obiekty zaczynają się nawzajem znać zbyt dobrze: formularze, panele administracyjne, pipeline komend, logika UI.
- Jego siłą jest mniejsza liczba zależności i prostsze testy, ale ceną bywa dodatkowa warstwa i ryzyko „przerośniętego” mediatora.
- W aplikacjach webowych często działa najlepiej jako koordynator, a nie miejsce na całą logikę biznesową.
- Najlepiej sprawdza się przy wielu regułach interakcji; przy prostych przepływach bywa zbędny.
Czym jest wzorzec Mediator i jaki problem rozwiązuje
To wzorzec behawioralny, w którym jeden obiekt przejmuje rolę koordynatora interakcji między wieloma innymi obiektami. Ja najczęściej tłumaczę go sobie bardzo praktycznie: zamiast sieci bezpośrednich wywołań dostajesz jedno miejsce, które wie, jak poprowadzić przepływ. Gdy masz 5 komponentów, liczba potencjalnych relacji robi się już zauważalna, a przy 8 elementach dochodzisz do 28 par połączeń. To nie jest matematyka dla ozdoby, tylko ilustracja tego, jak szybko kod zaczyna się rozlewać.
Mediator nie służy do wykonywania całej pracy za obiekty. Jego zadanie jest skromniejsze i ważniejsze: decydować, kto ma zareagować i w jakiej kolejności, a same komponenty zostawić możliwie proste. Dzięki temu łatwiej je testować, wymieniać i ponownie wykorzystywać. Kiedy ten obraz jest już jasny, warto zobaczyć, jak wygląda przepływ komunikacji krok po kroku.

Jak działa komunikacja przez pośrednika
W praktyce mediator opiera się na trzech rolach. Pierwsza to obiekty robocze, czyli komponenty, które wykonują własne zadania. Druga to sam mediator, który zbiera sygnały i uruchamia właściwe reakcje. Trzecia to konkretna implementacja mediatora, która zna reguły współpracy, ale nie musi znać szczegółów wszystkich klas w taki sposób, w jaki znają się one nawzajem w układzie bez pośrednika.
| Element | Rola | Co to daje |
|---|---|---|
| Komponenty | Wykonują lokalne zadania i zgłaszają zmiany | Nie muszą znać szczegółów innych obiektów |
| Mediator | Koordynuje komunikację i wybiera reakcję | Porządkuje przepływ i zmniejsza liczbę zależności |
| Konkretna implementacja | Zawiera reguły współpracy dla danego przypadku | Można zmienić logikę interakcji bez przepisywania wszystkich komponentów |
- Jeden komponent zgłasza zmianę stanu albo potrzebę działania.
- Mediator sprawdza kontekst i decyduje, które obiekty powinny zareagować.
- Wybrane komponenty dostają polecenie albo informację zwrotną.
- Komponenty nadal nie rozmawiają ze sobą bezpośrednio, więc ich zależności pozostają płytsze.
W dokumentacji Microsoft Learn ten układ pojawia się w aplikacjach ASP.NET Core: kontroler wysyła komendę do mediatora, a handler wykonuje właściwą pracę. To dobry przykład, bo pokazuje mediator nie jako teorię z książki, ale jako sposób na uproszczenie realnego przepływu w aplikacji. Żeby to nie zostało na poziomie schematu, spójrzmy na formularz, bo tam ten wzorzec widać najszybciej.
Przykład z formularza, który sam ustala reguły
W formularzu rejestracji albo ustawień zależności pojawiają się błyskawicznie. Checkbox „konto firmowe” odsłania pole NIP, wybór kraju zmienia walidację kodu pocztowego, a przycisk „Zapisz” aktywuje się dopiero wtedy, gdy spełnione są wszystkie warunki. Gdyby każda kontrolka znała resztę, logika rozrosłaby się w mały labirynt.
| Zdarzenie | Reakcja mediatora | Efekt dla użytkownika |
|---|---|---|
| Zaznaczono „konto firmowe” | Pokazuje pole NIP i uruchamia dodatkową walidację | Formularz reaguje na kontekst, a nie tylko na pojedyncze pole |
| Zmieniono kraj | Podmienia maskę kodu pocztowego i zestaw reguł adresowych | Mniej błędów wejściowych i mniej komunikatów po wysłaniu formularza |
| Hasło ma zbyt mało znaków | Blokuje zapis i pokazuje właściwy komunikat | Użytkownik od razu widzi, co trzeba poprawić |
Ja w takich przypadkach wolę, aby mediator był cienką warstwą koordynacji, a reguły walidacji trafiały do osobnych walidatorów. Dzięki temu formularz pozostaje czytelny, a zmiana jednego warunku nie wymaga grzebania w kilku kontrolkach naraz. To prowadzi do najważniejszego praktycznego pytania: kiedy ten wzorzec rzeczywiście warto dodać, a kiedy tylko powiększy kod?
Kiedy warto go stosować, a kiedy lepiej odpuścić
Ja sięgam po Mediatora wtedy, gdy zależności rosną szybciej niż sama funkcjonalność. To zwykle oznacza kilka lub kilkanaście obiektów, które zaczynają się wzajemnie obserwować, warunkować i blokować. Wtedy centralny pośrednik przestaje być ozdobą architektoniczną, a zaczyna realnie oszczędzać czas.
- Stosuj go, gdy liczba relacji między komponentami rośnie wraz z rozwojem funkcji.
- Stosuj go, gdy reguły współpracy zmieniają się częściej niż same komponenty.
- Stosuj go, gdy chcesz centralnie ogarnąć walidację, logowanie, audyt albo autoryzację przepływu.
- Stosuj go, gdy budujesz UI z wieloma współzależnymi kontrolkami albo command pipeline po stronie backendu.
- Nie stosuj go, gdy interakcja jest prosta i obejmuje 2-3 klasy.
- Nie stosuj go, gdy pośrednik zaczyna przejmować biznesowe decyzje i zamienia się w God Object.
- Nie stosuj go, gdy masz lepszy model komunikacji zdarzeniowej lub wyraźne granice komponentów.
- Nie stosuj go, gdy koszt dodatkowej abstrakcji jest większy niż zysk z uporządkowania zależności.
W praktyce zbyt wczesne wprowadzenie wzorca potrafi zaszkodzić bardziej niż jego brak. Jeśli przepływ jest prosty, proste wywołanie zwykle wygrywa. Gdy jednak rośnie liczba reguł i wyjątków, mediator zaczyna zwracać inwestycję bardzo szybko. Następny krok to odróżnienie go od kilku podobnych mechanizmów, bo tu najłatwiej o mylne decyzje.
Mediator, Observer, Facade i event bus w praktyce
Te wzorce bywają wrzucane do jednego worka, ale rozwiązują różne problemy. Ja patrzę na nie tak: Mediator porządkuje współpracę między równorzędnymi obiektami, Observer rozsyła informację o zmianie stanu, Facade upraszcza dostęp do złożonego subsystemu, a event bus daje luźniejsze, zdarzeniowe połączenie między nadawcami i odbiorcami.
| Wzorzec | Główna rola | Kiedy pasuje najlepiej |
|---|---|---|
| Mediator | Koordynuje interakcje między obiektami | Gdy wiele komponentów wpływa na siebie nawzajem |
| Observer | Powiadamia zainteresowanych o zmianie stanu | Gdy jeden obiekt ma wielu odbiorców reakcji |
| Facade | Ukrywa złożoność pod prostym interfejsem | Gdy chcesz uprościć korzystanie z subsystemu |
| Event bus | Przekazuje zdarzenia między producentami i konsumentami | Gdy komunikacja ma być bardziej pośrednia i rozproszona |
Jeśli po tej tabeli nadal brzmi to podobnie, zapamiętaj jedną rzecz: Mediator odpowiada na pytanie „kto z kim i kiedy współpracuje?”, a nie „jak ukryć bibliotekę” ani „komu wysłać event”. To dobry moment, żeby zobaczyć typowe pułapki implementacyjne, bo one decydują o tym, czy wzorzec realnie pomaga.
Najczęstsze błędy przy wdrażaniu i jak ich uniknąć
- Zbyt gruby mediator. Jeśli cały biznes ląduje w jednym obiekcie, zyskujesz tylko nowy wąskie gardło. Trzymaj w nim koordynację, nie całą domenę.
- Mieszanie reguł z transportem. Mediator nie powinien sam liczyć wszystkiego od A do Z. Walidację, transformację i decyzje dziel tam, gdzie mają sens.
- Wprowadzanie wzorca na siłę. Przy dwóch klasach mediator często jest zbędny. Wtedy prostszy kod wygrywa z elegancką abstrakcją.
- Brak granic odpowiedzialności. Jeśli nie wiadomo, za co mediator odpowiada, a za co nie, testy szybko stają się kruche. Ja lubię opisać to jednym zdaniem jeszcze przed implementacją.
W .NET i ASP.NET Core ten problem jest dobrze widoczny przy kontrolerach: Microsoft Learn pokazuje, że mediator pomaga odchudzić konstruktor i przekazać pracę handlerom, ale tylko wtedy, gdy sam mediator nie zaczyna być kolejną monolityczną usługą. Gdy zasada „koordynuj, nie duplikuj logiki” jest pilnowana, wzorzec pozostaje czytelny. Zostaje jeszcze ostatnia kwestia: jak ocenić, czy w twoim projekcie to faktycznie się opłaci.
Jak oceniam, czy mediator naprawdę się opłaci w projekcie
Przed wdrożeniem sprawdzam cztery rzeczy: czy zależności rosną szybciej niż sama funkcja, czy interakcje zmieniają się częściej niż komponenty, czy potrzebuję jednego miejsca dla logowania i walidacji, oraz czy pośrednik da się opisać jednym prostym zdaniem. Jeśli na dwa z tych pytań odpowiadam „nie”, zwykle zostawiam prostsze wywołania. Jeśli na trzy odpowiadam „tak”, Mediator zaczyna być rozsądnym wyborem, nie tylko ładnym wzorcem z książki.
W projekcie webowym traktuję go więc jak narzędzie do porządkowania komunikacji, a nie obowiązkowy element architektury. Dobrze użyty upraszcza rozwój i testy; źle użyty przenosi chaos do jednego miejsca. I właśnie ta różnica najczęściej decyduje o tym, czy wzorzec pomaga zespołowi, czy tylko wygląda dojrzale na diagramie.