3.5. Mediator

3.5.1. Purpose

This pattern provides an easy way to decouple many components working together. It is a good alternative to Observer IF you have a «central intelligence», like a controller (but not in the sense of the MVC).

All components (called Colleague) are only coupled to the Mediator interface and it is a good thing because in OOP, one good friend is better than many. This is the key-feature of this pattern.

3.5.2. UML Diagram

Alt Mediator UML Diagram

3.5.3. Code

You can also find this code on GitHub

Mediator.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Behavioral\Mediator;
 6
 7interface Mediator
 8{
 9    public function getUser(string $username): string;
10}

Colleague.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Behavioral\Mediator;
 6
 7abstract class Colleague
 8{
 9    protected Mediator $mediator;
10
11    final public function setMediator(Mediator $mediator)
12    {
13        $this->mediator = $mediator;
14    }
15}

Ui.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Behavioral\Mediator;
 6
 7class Ui extends Colleague
 8{
 9    public function outputUserInfo(string $username)
10    {
11        echo $this->mediator->getUser($username);
12    }
13}

UserRepository.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Behavioral\Mediator;
 6
 7class UserRepository extends Colleague
 8{
 9    public function getUserName(string $user): string
10    {
11        return 'User: ' . $user;
12    }
13}

UserRepositoryUiMediator.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Behavioral\Mediator;
 6
 7class UserRepositoryUiMediator implements Mediator
 8{
 9    public function __construct(private UserRepository $userRepository, private Ui $ui)
10    {
11        $this->userRepository->setMediator($this);
12        $this->ui->setMediator($this);
13    }
14
15    public function printInfoAbout(string $user)
16    {
17        $this->ui->outputUserInfo($user);
18    }
19
20    public function getUser(string $username): string
21    {
22        return $this->userRepository->getUserName($username);
23    }
24}

3.5.4. Test

Tests/MediatorTest.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Tests\Mediator\Tests;
 6
 7use DesignPatterns\Behavioral\Mediator\Ui;
 8use DesignPatterns\Behavioral\Mediator\UserRepository;
 9use DesignPatterns\Behavioral\Mediator\UserRepositoryUiMediator;
10use PHPUnit\Framework\TestCase;
11
12class MediatorTest extends TestCase
13{
14    public function testOutputHelloWorld()
15    {
16        $mediator = new UserRepositoryUiMediator(new UserRepository(), new Ui());
17
18        $this->expectOutputString('User: Dominik');
19        $mediator->printInfoAbout('Dominik');
20    }
21}