Home > Article > Backend Development > Adaptable Visitor Pattern
One day, the technical director said he wanted to know the work status of all technical employees. The next day, the boss said he wanted to know the performance of all employees. Another day, the HR director wanted to know the salaries of all employees. Each time, the combination mode is used to traverse the employees and obtain the relevant information of the employees. Maybe you will say that you can just output all the information. Then you are probably going to be caught by the boss. The boss wants to know the performance. If you look at a big table, okay, you can go home! Let the visitor pattern help us solve this problem. The class diagram is as follows:
As you can see, there is a visitor, which is the visitor, and it seems a bit like an agent. When talking about the proxy mode, we have already mentioned the visitor mode. This purchase uses the proxy mode on more special occasions. Implementation code:
<?php interface IVisitor{ public function visitCommonEmployee( CommonEmployee $commonEmployee ); public function visitManager( Manager $manager ); } class Visitor implements IVisitor{ public function visitCommonEmployee( CommonEmployee $commonEmployee ) { echo $this->getCommonEmployee( $commonEmployee ); } public function visitManager( Manager $manager ) { echo $this->getManagerInfo( $manager ); } private function getBasicInfo( Employee $employee ) { $info = "姓名:".$employee->getName()."\t"; return $info; } private function getCommonEmployee( CommonEmployee $commonEmployee ) { $basicInfo = $this->getBasicInfo( $commonEmployee ); $otherInfo = "工作:".$commonEmployee->getJob()."\n"; return $basicInfo.$otherInfo; } private function getManagerInfo( Manager $manager ) { $basicInfo = $this->getBasicInfo( $manager ); $otherInfo = "业绩:".$manager->getPerformance()."\n"; return $basicInfo.$otherInfo; } } abstract class Employee { private $name; public function getName() { return $this->name; } public function setName( $name ) { $this->name = $name; } public function accept( IVisitor $visitor ) { $method = 'visit'.get_class( $this ); $visitor->$method( $this ); } } class CommonEmployee extends Employee{ private $job; public function getJob() { return $this->job; } public function setJob( $job ) { $this->job = $job; } } class Manager extends Employee{ private $performance; public function getPerformance() { return $this->performance; } public function setPerformance( $performance ) { $this->performance = $performance; } } $empList = array(); $zhangsan = new CommonEmployee(); $zhangsan->setName( '张三' ); $zhangsan->setJob( 'coding' ); $empList[] = $zhangsan; $lisi = new CommonEmployee(); $lisi->setName( '李四' ); $lisi->setJob( 'coding' ); $empList[] = $lisi; $wangwu = new Manager(); $wangwu->setName( '马云' ); $wangwu->setPerformance( '负值,但拍马屁厉害' ); $empList[] = $wangwu; foreach ($empList as $value) { $value->accept(new Visitor()); } ?>
Operating results:
Name: Zhang San Job: coding
Name: Li Si Job: coding
Name: Jack Ma Performance: Negative, but flattering is awesome
[Finished in 0.4s]
If there is any special list in the future, I only need to add a special visitor. Now the boss can't abuse me!
The definition of visitor pattern
encapsulates some operations that act on each element in a certain data structure. It can define new operations that act on these elements without changing the data structure. The main roles are:
1. VIsitor - abstract visitor
Abstract class interface, which declares which elements the visitor can access. Specific to the program, the parameters of the visit method define which objects can be accessed.
2. Concrete Visitor——Concrete visitor
It affects what the visitor should do after visiting a class.
3. Element——Abstract element
Interface or abstract class, which declares which type of visitor is accepted. Programmatically, it is defined through the parameters in the accept method.
4. ConcreteElement - Concrete element
implements the accept method, usually visitor->visitor($this), which basically forms a pattern.
5. ObjectStruture - Structure object
element generator, generally accommodating multiple containers of different classes and interfaces.
Advantages of the visitor pattern
1. Comply with the single responsibility principle
The specific element roles are two subclasses of the Employee abstract class responsible for loading data, while the Visitor class is responsible for the presentation of reports, two different responsibilities Very clearly separated, each performs changes.
2. Excellent scalability
Due to the separation of responsibilities, it is very fast to continue to add operations on data. For example, if you want to add a report to the big boss, you can directly add a method in the Visitor to transfer the data and then organize and print it. .
3. Very high flexibility
For example, suppose you need to calculate the total salary at the same time as the report
Disadvantages of the visitor model
1. Specific elements publish details to visitors
Visitors must access a class This class publishes some methods and data, which means that visitors pay attention to the internal details of other classes, which is not recommended by Demeter's Law.
2. It is difficult to change specific elements
It is difficult to add, delete and modify the role of specific elements. In the above example, if you want to add a member variable, such as age, the Visitor needs to be modified. If the Visitor is more than One, does that mean everyone needs to be changed?
3. Violates the principle of dependency inversion
Visitors rely on concrete elements rather than abstract elements, which destroys the principle of dependency inversion, especially in object-oriented programming, which abandons dependence on interfaces and directly relies on It is difficult to implement classes and extensions.
Usage scenarios of visitor pattern
1. An object structure contains many class objects, they have different interfaces, and you want to perform some operations on these objects that depend on their specific classes, which means that the iterator pattern can no longer Competent situation.
2. Many different and unrelated operations need to be performed on the objects in an object structure, and you want to avoid letting these operations "pollute" the classes of these objects
Extension of the visitor pattern
1. Statistics function
For example, if you want to count the wages of all employees, you only need to add a method to the interface and implement it in a specific class.
2. Multiple visitors
As I said before, if different visitors have different report requirements, then just add a Visitor class implementation directly.
3. Dual dispatch (JAVA)
Nagging: Visitor mode is a centralized and regular mode, especially suitable for large-scale reconstruction. At this stage, the requirements have been very clear, and the functional points of the original system have also been It is clear that through the visitor mode, some functions can be easily sorted out to achieve the final goal - function centralization, such as a unified report operation, UI display, etc. It can also be blended with other modes to create its own set of filters or interceptors .