PHP design pattern series-Visitor pattern (Visitor) 1. Pattern Definition
We will go to the bank counter to handle the business. generally, we will open several individual business counters. you can go to any of them to handle the work. Our visitor model can be well put into this scenario: for bank counters, they do not need to change, that is, the counters that provide personal services today and tomorrow do not need to change. As a visitor, we may come to the bank today to fetch the consumption flow. tomorrow we may come to the bank to handle the mobile banking business. these are the operations of our visitors, which have been changing.
The visitor mode is an operation that acts on each element in an object structure. It allows you to define new operations that act on these elements without changing the classes of each element.
2. UML class diagram
3. sample code RoleVisitorInterface. php
RolePrintVisitor. php
GetName () ;}/ *** {@ inheritdoc} */public function visitUser (User $ role) {echo "Role:". $ role-> getName ();}}
Role. php
User. php
name = (string) $name; } /** * @return string */ public function getName() { return "User " . $this->name; }}
Group. php
name = (string) $name; } /** * @return string */ public function getName() { return "Group: " . $this->name; }}
4. test code Tests/VisitorTest. php
Visitor = new Visitor \ RolePrintVisitor ();} public function getRole () {return array (new Visitor \ User ("Dominik"), 'role: User Dominik '), array (new Visitor \ Group ("Administrators"), 'role: Group: Administrators '));} /*** @ dataProvider getRole */public function testVisitSomeRole (Visitor \ Role $ role, $ predict CT) {$ this-> expectOutputString ($ predict CT ); $ role-> accept ($ this-> visitor);}/*** @ expectedException \ InvalidArgumentException * @ expectedExceptionMessage Mock */public function testUnknownObject () {$ mock = $ this-> getMockForAbstractClass ('designpatterns \ Behavioral \ Visitor \ role'); $ mock-> accept ($ this-> visitor );}}
5. SummaryThe visitor mode is suitable for systems with relatively stable data structures. it frees the coupling between the data structure and the operations acting on the structure, allowing the operation set to evolve freely. In this example, User and Group are data structures, while RolePrintVisitor are visitors (used for operations above the structure ).
When implementing the Visitor mode, put as many object browsing logic as possible in the Visitor class, rather than in its subclass. in this case, the ConcreteVisitor class has less dependencies on the object structure, making maintenance easier.