Design Patterns Java - Visitor Php

1) What have we done first?

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


public interface Visitor
{
    void visitClassA(ClassA classA);

    void visitClassB(ClassB classB);
}

public class ConcreteVisitor implements Visitor
{
    @Override
    public void visitClassA(ClassA classA)
    {
        classA.doA();
    }

    @Override
    public void visitClassB(ClassB classB)
    {
        classB.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"


public class ClassA implements CommonInterface
{
    @Override
    public void doCommonAction()
    {
        System.out.println("ClassA doing common");
    }

    public void doA()
    {
        System.out.println("ClassA doing A");
    }

    @Override
    public void accept(Visitor v)
    {
        v.visitClassA(this);
    }
}

public class ClassB implements CommonInterface
{
    @Override
    public void doCommonAction()
    {
        System.out.println("ClassB doing common");
    }

    public void doB()
    {
        System.out.println("ClassB doing B");
    }

    @Override
    public void accept(Visitor v)
    {
        v.visitClassB(this);
    }
}

public interface CommonInterface
{
    void doCommonAction();

    void accept(Visitor v);
}




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


import java.util.List;

public class Client
{
    public void traverseCollection(List<CommonInterface> collection)
    {
        Visitor visitor = new ConcreteVisitor();
        collection.stream().forEach((s) -> s.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"