Mediator Pattern
Purpose
The purpose of the design pattern
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.
UML
UML design pattern diagram

Code
Code snippets
Mediator
Mediator Interface which defines a getUser method signature.
namespace DesignPatterns\Behavioral\Mediator;
interface Mediator
{
public function getUser(string $username): string;
}
Colleague
Abstract class Colleague which eliminates boilerplate code throughout any concrete subclasses which extend it. The setMediator method is final meaning it cannot be overridden by a sub class.
namespace DesignPatterns\Behavioral\Mediator;
abstract class Colleague
{
protected Mediator $mediator;
final public function setMediator(Mediator $mediator)
{
$this->mediator = $mediator;
}
}
Ui
Ui extends Colleague and contains an outputUserInfo method. This method references the mediators getUser method.
namespace DesignPatterns\Behavioral\Mediator;
class Ui extends Colleague
{
public function outputUserInfo(string $username)
{
echo $this->mediator->getUser($username);
}
}
UserRepository
UserRepository extends Colleague and has a getUserName method.
namespace DesignPatterns\Behavioral\Mediator;
class UserRepository extends Colleague
{
public function getUserName(string $user): string
{
return 'User: ' . $user;
}
}
UserRepositoryUiMediator
The UserRepositoryUiMediator expects the UserRepository and Ui classes as construct parameters. This class proxies methods within those classes.
namespace DesignPatterns\Behavioral\Mediator;
class UserRepositoryUiMediator implements Mediator
{
public function __construct(private UserRepository $userRepository, private Ui $ui)
{
$this->userRepository->setMediator($this);
$this->ui->setMediator($this);
}
public function printInfoAbout(string $user)
{
$this->ui->outputUserInfo($user);
}
public function getUser(string $username): string
{
return $this->userRepository->getUserName($username);
}
}
MediatorTest
MediatorTest example below. The mediator design pattern decouples components which all work together. A separation of concerns allows code to be reused and switched out easily.
namespace DesignPatterns\Tests\Mediator\Tests;
use DesignPatterns\Behavioral\Mediator\Ui;
use DesignPatterns\Behavioral\Mediator\UserRepository;
use DesignPatterns\Behavioral\Mediator\UserRepositoryUiMediator;
use PHPUnit\Framework\TestCase;
class MediatorTest extends TestCase
{
public function testOutputHelloWorld()
{
$mediator = new UserRepositoryUiMediator(new UserRepository(), new Ui());
$this->expectOutputString('User: Dominik');
$mediator->printInfoAbout('Dominik');
}
}
Ready to bring your vision to life?
We believe in excellence, empathy, integrity, and transparency throughout the process. Our goal is to build fast, responsive websites that not only perform but also reflect your values and vision.