3.4. Mediator
3.4.1. Purpose
This pattern provides an easy way to decouple many components workingtogether. It is a good alternative to Observer IF you have a “centralintelligence”, like a controller (but not in the sense of the MVC).
All components (called Colleague) are only coupled to theMediatorInterface and it is a good thing because in OOP, one good friendis better than many. This is the key-feature of this pattern.
3.4.2. UML Diagram
3.4.3. Code
You can also find this code on GitHub
MediatorInterface.php
- <?php
- namespace DesignPatterns\Behavioral\Mediator;
- /**
- * MediatorInterface is a contract for the Mediator
- * This interface is not mandatory but it is better for Liskov substitution principle concerns.
- */
- interface MediatorInterface
- {
- /**
- * sends the response.
- *
- * @param string $content
- */
- public function sendResponse($content);
- /**
- * makes a request
- */
- public function makeRequest();
- /**
- * queries the DB
- */
- public function queryDb();
- }
Mediator.php
- <?php
- namespace DesignPatterns\Behavioral\Mediator;
- /**
- * Mediator is the concrete Mediator for this design pattern
- *
- * In this example, I have made a "Hello World" with the Mediator Pattern
- */
- class Mediator implements MediatorInterface
- {
- /**
- * @var Subsystem\Server
- */
- private $server;
- /**
- * @var Subsystem\Database
- */
- private $database;
- /**
- * @var Subsystem\Client
- */
- private $client;
- /**
- * @param Subsystem\Database $database
- * @param Subsystem\Client $client
- * @param Subsystem\Server $server
- */
- public function __construct(Subsystem\Database $database, Subsystem\Client $client, Subsystem\Server $server)
- {
- $this->database = $database;
- $this->server = $server;
- $this->client = $client;
- $this->database->setMediator($this);
- $this->server->setMediator($this);
- $this->client->setMediator($this);
- }
- public function makeRequest()
- {
- $this->server->process();
- }
- public function queryDb(): string
- {
- return $this->database->getData();
- }
- /**
- * @param string $content
- */
- public function sendResponse($content)
- {
- $this->client->output($content);
- }
- }
Colleague.php
- <?php
- namespace DesignPatterns\Behavioral\Mediator;
- /**
- * Colleague is an abstract colleague who works together but he only knows
- * the Mediator, not other colleagues
- */
- abstract class Colleague
- {
- /**
- * this ensures no change in subclasses.
- *
- * @var MediatorInterface
- */
- protected $mediator;
- /**
- * @param MediatorInterface $mediator
- */
- public function setMediator(MediatorInterface $mediator)
- {
- $this->mediator = $mediator;
- }
- }
Subsystem/Client.php
- <?php
- namespace DesignPatterns\Behavioral\Mediator\Subsystem;
- use DesignPatterns\Behavioral\Mediator\Colleague;
- /**
- * Client is a client that makes requests and gets the response.
- */
- class Client extends Colleague
- {
- public function request()
- {
- $this->mediator->makeRequest();
- }
- public function output(string $content)
- {
- echo $content;
- }
- }
Subsystem/Database.php
- <?php
- namespace DesignPatterns\Behavioral\Mediator\Subsystem;
- use DesignPatterns\Behavioral\Mediator\Colleague;
- class Database extends Colleague
- {
- public function getData(): string
- {
- return 'World';
- }
- }
Subsystem/Server.php
- <?php
- namespace DesignPatterns\Behavioral\Mediator\Subsystem;
- use DesignPatterns\Behavioral\Mediator\Colleague;
- class Server extends Colleague
- {
- public function process()
- {
- $data = $this->mediator->queryDb();
- $this->mediator->sendResponse(sprintf("Hello %s", $data));
- }
- }
3.4.4. Test
Tests/MediatorTest.php
- <?php
- namespace DesignPatterns\Tests\Mediator\Tests;
- use DesignPatterns\Behavioral\Mediator\Mediator;
- use DesignPatterns\Behavioral\Mediator\Subsystem\Client;
- use DesignPatterns\Behavioral\Mediator\Subsystem\Database;
- use DesignPatterns\Behavioral\Mediator\Subsystem\Server;
- use PHPUnit\Framework\TestCase;
- class MediatorTest extends TestCase
- {
- public function testOutputHelloWorld()
- {
- $client = new Client();
- new Mediator(new Database(), $client, new Server());
- $this->expectOutputString('Hello World');
- $client->request();
- }
- }