Відвідувач

Аналогія

Туристи зібралися до Дубаї. Спочатку їм потрібен спосіб потрапити туди (віза). Після прибуття вони відвідуватимуть будь-яку частину міста, не питаючи дозволу, ходити де заманеться. Просто скажіть їм про якесь місце — і туристи можуть там побувати. Шаблон відвідувачів допомагає додавати місця для відвідування.

Стисло

Шаблон «Відвідувач» дозволяє додавати майбутні операції для об’єктів без їхнього модифікування.

Вікіпедія

Шаблон “Відвідувач” – це спосіб відокремлення алгоритму від структури об’єкта, в якій він оперує. Результат відділення – можливість додавати нові операції до існуючих структур об’єктів без їх модифікування. Це один із способів дотримання принципу відкритості/закритості (open/closed principle).

Приклад

Візьмемо зоопарк: у нас є кілька видів тварин, і нам потрібно послухати звуки, які вони видають.

// Місце відвідування
interface Animal
{
    public function accept(AnimalOperation $operation);
}

// Відвідувач
interface AnimalOperation
{
    public function visitMonkey(Monkey $ monkey);
    public function visitLion(Lion $lion);
    public function visitDolphin(Dolphin $dolphin);
}

Реалізуємо тварин:

class Monkey implements Animal
{
    public function shout()
    {
        echo 'Ooh oo aa aa!';
    }

    public function accept(AnimalOperation $operation)
    {
        $operation->visitMonkey($this);
    }
}

class Lion implements Animal
{
    public function roar()
    {
        echo 'Roaaar!';
    }

    public function accept(AnimalOperation $operation)
    {
        $operation->visitLion($this);
    }
}

class Dolphin implements Animal
{
    public function speak()
    {
        echo 'Tuut tuttu tuutt!';
    }

    public function accept(AnimalOperation $operation)
    {
        $operation->visitDolphin($this);
    }
}

Реалізуємо відвідувача:

class Speak implements AnimalOperation
{
    public function visitMonkey(Monkey $monkey)
    {
        $monkey->shout();
    }

    public function visitLion(Lion $lion)
    {
        $lion->roar();
    }

    public function visitDolphin(Dolphin $dolphin)
    {
        $dolphin->speak();
    }
}

Використання:

$ Monkey = New Monkey ();
$ lion = New Lion ();
$ dolphin = New Dolphin ();

$ Speak = New Speak ();

$monkey->accept($speak); // Уа-уа-уааааа!
$lion->accept($speak); // Ррррррррр!
$dolphin->accept($speak); // Туут тутт туут!

Це можна було зробити просто за допомогою ієрархії успадкування, але тоді довелося модифікувати тварин при кожному додаванні до них нових дій. А тут міняти їх не треба. Наприклад, ми можемо додати тваринам стрибки, створивши нового відвідувача:

class Jump implements AnimalOperation
{
    public function visitMonkey(Monkey $monkey)
    {
        echo 'Jumped 20 feet high! on to the tree!';
    }

    public function visitLion(Lion $lion)
    {
        echo 'Jumped 7 feet! Back on the ground!';
    }

    public function visitDolphin(Dolphin $dolphin)
    {
        echo 'Walked on water a little and disappeared';
    }
}

Використання:

$jump = новий Jump();

$monkey->accept($speak); // Ooh oo aa aa!
$monkey->accept($jump); // Jumped 20 feet high! on to the tree!

$lion->accept($speak); // Roaaar!
$lion->accept($jump); // Jumped 7 feet! Back on the ground!

$dolphin->accept($speak); // Tuut tutt tuutt!
$dolphin->accept($jump); // Walked on water a little and disappeared

Залишити коментар