目的
訪問者パターンを使用すると、オブジェクト操作を他のオブジェクトに外部委託できます。
これの主な理由は、懸念事項の分離(データ構造とデータ操作)です。ただし、訪問されるクラスは、訪問者を受け入れる契約を結ぶ必要があります。(詳細については、例のRole :: acceptメソッドを参照してください)
コントラクトは、抽象クラスまたはインターフェイスにすることができます。この場合、各訪問者は訪問者のどのメソッドを呼び出すかを選択する必要があります。
UML图
コード
- RoleVisitorInterface.php
<?php
namespace DesignPatterns\Behavioral\Visitor;
/**
* 注意:访问者不能自行选择调用哪个方法,
* 它是由 Visitee 决定的。
*/
interface RoleVisitorInterface
{
public function visitUser(User $role);
public function visitGroup(Group $role);
}
- RoleVisitor.php
<?php
namespace DesignPatterns\Behavioral\Visitor;
class RoleVisitor implements RoleVisitorInterface
{
/**
* @var Role[]
*/
private $visited = [];
public function visitGroup(Group $role)
{
$this->visited[] = $role;
}
public function visitUser(User $role)
{
$this->visited[] = $role;
}
/**
* @return Role[]
*/
public function getVisited(): array
{
return $this->visited;
}
}
- Role.php
<?php
namespace DesignPatterns\Behavioral\Visitor;
interface Role
{
public function accept(RoleVisitorInterface $visitor);
}
- User.php
<?php
namespace DesignPatterns\Behavioral\Visitor;
class User implements Role
{
/**
* @var string
*/
private $name;
public function __construct(string $name)
{
$this->name = $name;
}
public function getName(): string
{
return sprintf('User %s', $this->name);
}
public function accept(RoleVisitorInterface $visitor)
{
$visitor->visitUser($this);
}
}
- Group.php
<?php
namespace DesignPatterns\Behavioral\Visitor;
class Group implements Role
{
/**
* @var string
*/
private $name;
public function __construct(string $name)
{
$this->name = $name;
}
public function getName(): string
{
return sprintf('Group: %s', $this->name);
}
public function accept(RoleVisitorInterface $visitor)
{
$visitor->visitGroup($this);
}
}
テスト
- Tests / VisitorTest.php
<?php
namespace DesignPatterns\Tests\Visitor\Tests;
use DesignPatterns\Behavioral\Visitor;
use PHPUnit\Framework\TestCase;
class VisitorTest extends TestCase
{
/**
* @var Visitor\RoleVisitor
*/
private $visitor;
protected function setUp()
{
$this->visitor = new Visitor\RoleVisitor();
}
public function provideRoles()
{
return [
[new Visitor\User('Dominik')],
[new Visitor\Group('Administrators')],
];
}
/**
* @dataProvider provideRoles
*
* @param Visitor\Role $role
*/
public function testVisitSomeRole(Visitor\Role $role)
{
$role->accept($this->visitor);
$this->assertSame($role, $this->visitor->getVisited()[0]);
}
}
PHP Internet Architectの成長パス*「デザインパターン」の究極のガイド
PHP Internet Architect 50K Growth Guide + Industry Problem Solving Guide(Continuous Update)
10社へのインタビュー、9件のオファー、2020年のPHPインタビューの質問
★私の記事が好きで、より多くの上級開発者とコミュニケーションを取り、学びたい場合は、主要企業へのインタビューに関連するより多くの技術的なコンサルティングとガイダンスを取得してください。
2020年の最新のPHP高度なチュートリアル、フルシリーズ!
内容が良かったら、いいね、いいね!を付けて、コミュニケーションを歓迎します。また、質問がある場合は、コメントで見たいものを提案してください。