Visitor Pattern

This is an example of a Visitor Pattern.

This pattern allows us to separate logic from the objects on which it operates. It is mainly used when a need to perform operations on various objects arises. Let's say the operation that needs to be performed is auxiliary behaviour and does not belong to the business logic.
Setting up a visitor is a great solution to provide the functionality without adding logic directly in the object.

The easiest to remember use-case for a Visitor Pattern could be when you are trying to add XML or CSV export functionalities to some of your models.
Because it is not the concern of your model, you would not want to add an exportXML and exportCSV method to your model. You can solve this by using a Visitor Pattern and move that functionality to your concrete Visitor.

Put simply, instead of doing Visitee.exportXML() and Visitee.exportCSV() respectively, you will be able to do Visitee.export(XMLExportVisitor) or Visitee.export(CSVExportVisitor).

Visitor A

Will use FirstConcreteVisitor to apply logic and will print that it is applying First Action.

I am applying first action on App\PatternVisitor\VisiteeA: Hello, I am an A
I am applying first action on App\PatternVisitor\VisiteeB: Hello, I am a B
I am applying first action on App\PatternVisitor\VisiteeA: Hello, I am an A
I am applying first action on App\PatternVisitor\VisiteeB: Hello, I am a B
I am applying first action on App\PatternVisitor\VisiteeA: Hello, I am an A
I am applying first action on App\PatternVisitor\VisiteeB: Hello, I am a B
I am applying first action on App\PatternVisitor\VisiteeA: Hello, I am an A
I am applying first action on App\PatternVisitor\VisiteeB: Hello, I am a B
I am applying first action on App\PatternVisitor\VisiteeA: Hello, I am an A
I am applying first action on App\PatternVisitor\VisiteeB: Hello, I am a B

Visitor B

Will use SecondConcreteVisitor to apply logic and will say it is applying Second Action.

I am applying second action on App\PatternVisitor\VisiteeA: Hello, I am an A
I am applying second action on App\PatternVisitor\VisiteeB: Hello, I am a B
I am applying second action on App\PatternVisitor\VisiteeA: Hello, I am an A
I am applying second action on App\PatternVisitor\VisiteeB: Hello, I am a B
I am applying second action on App\PatternVisitor\VisiteeA: Hello, I am an A
I am applying second action on App\PatternVisitor\VisiteeB: Hello, I am a B
I am applying second action on App\PatternVisitor\VisiteeA: Hello, I am an A
I am applying second action on App\PatternVisitor\VisiteeB: Hello, I am a B
I am applying second action on App\PatternVisitor\VisiteeA: Hello, I am an A
I am applying second action on App\PatternVisitor\VisiteeB: Hello, I am a B

Visitor C

Let's say a new feature is required. Simply create a new Visitor class and write the logic there.

I am the latest addition and I perform action X on App\PatternVisitor\VisiteeA objects.
I am the latest addition and I perform action X on App\PatternVisitor\VisiteeB objects.
I am the latest addition and I perform action X on App\PatternVisitor\VisiteeA objects.
I am the latest addition and I perform action X on App\PatternVisitor\VisiteeB objects.
I am the latest addition and I perform action X on App\PatternVisitor\VisiteeA objects.
I am the latest addition and I perform action X on App\PatternVisitor\VisiteeB objects.
I am the latest addition and I perform action X on App\PatternVisitor\VisiteeA objects.
I am the latest addition and I perform action X on App\PatternVisitor\VisiteeB objects.
I am the latest addition and I perform action X on App\PatternVisitor\VisiteeA objects.
I am the latest addition and I perform action X on App\PatternVisitor\VisiteeB objects.