Design Patterns PHP - Visitor Java

1) What have we done first?

We created "Visitor" interface and define methods "visitClassA" and "visitClassB".
We also created one concrete class "ConcreteVisitor"


interface Visitor
{
    public function visitClassA(ClassA $a);

    public function visitClassB(ClassB $b);
}

class ConcreteVisitor implements Visitor
{
    public function visitClassA(ClassA $a)
    {
        $a->doA();
    }

    public function visitClassB(ClassB $b)
    {
        $b->doB();
    }
}




In these methods we just implement what "Client" want from our structure(so methods "doA" for "ClassA" and method "doB" for "ClassB"
If we want something different we just can implement another concrete visitor.

3) What has changed in "ClassA" and "ClassB"?

For the common interface we just add method "accept" which take as argument "Visitor"


class ClassA implements CommonInterface
{
    public function doCommonAction()
    {
        echo 'ClassA doing common action' . PHP_EOL;
    }

    public function doA()
    {
        echo 'ClassA doing A action' . PHP_EOL;
    }

    public function accept(Visitor $v)
    {
        $v->visitClassA($this);
    }
}

class ClassB implements CommonInterface
{
    public function doCommonAction()
    {
        echo 'ClassB doing common action' . PHP_EOL;
    }

    public function doB()
    {
        echo 'ClassB doing B action' . PHP_EOL;
    }

    public function accept(Visitor $v)
    {
        $v->visitClassB($this);
    }
}

interface CommonInterface
{
    public function doCommonAction();

    public function accept(Visitor $v);
}




As we can see in client "Client" instead of checking what concrete type is we just call method "accept"


$visitor = new ConcreteVisitor();

foreach ($collection as $object) {
    $object->accept($visitor);
}




In step1
- Client directly called method "doA" and "doB"

Now
- Client just call method "accept"
- Concrete class for example "ClassA" call method "visitClassA"
- And finally "Visitor" invoke method "doA"

So theoretically we just hamper our code instead of one line we just have three.

Generally speaking flow control is more complicated but in return we have
- nice simple code in Client
- concrete operations encapsulated in one object "ConcreteVisitor"