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
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}