中介者模式

目的

中介者模式提供了一种简单的方法来解耦多个组件并让它们一起工作。如果你有一个“中央智能”对象,比如一个控制器(但不是 MVC 意义上的控制器),那么,它将是观察者模式的一个很好的替代品。

所有的组件(这些称为“同事”)都只与中介者接口产生关系,这是一种不错的设计,因为在面向对象程序设计中,一对一的关系比一对多要好。这是中介者模式的关键所在。

UML 类图

中介者模式类图

代码

Mediator.php

1
2
3
4
5
6
7
8
<?php declare(strict_types = 1);

namespace DesignPatterns\Behavioral\Mediator;

interface Mediator
{
public function getUser(string $username): string;
}

Colleague.php

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php declare(strict_types = 1);

namespace DesignPatterns\Behavioral\Mediator;

abstract class Colleague
{
protected Mediator $mediator;

public function setMediator(Mediator $mediator)
{
$this->mediator = $mediator;
}
}

Ui.php

1
2
3
4
5
6
7
8
9
10
11
<?php declare(strict_types = 1);

namespace DesignPatterns\Behavioral\Mediator;

class Ui extends Colleague
{
public function outputUserInfo(string $username)
{
echo $this->mediator->getUser($username);
}
}

UserRepository.php

1
2
3
4
5
6
7
8
9
10
11
<?php declare(strict_types = 1);

namespace DesignPatterns\Behavioral\Mediator;

class UserRepository extends Colleague
{
public function getUserName(string $user): string
{
return 'User: ' . $user;
}
}

UserRepositoryUiMediator.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?php declare(strict_types = 1);

namespace DesignPatterns\Behavioral\Mediator;

class UserRepositoryUiMediator implements Mediator
{
private UserRepository $userRepository;
private Ui $ui;

public function __construct(UserRepository $userRepository, Ui $ui)
{
$this->userRepository = $userRepository;
$this->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);
}
}

测试

Tests/MediatorTest.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php declare(strict_types = 1);

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');
}
}