php visitor pattern implementation

Keywords: PHP Design Pattern

summary

Visitor pattern: represents an operation that acts on elements in an object structure. It allows you to define new operations on elements without changing their classes.

This paper takes the motorcycle manufacturer as an example. Due to market competition and long-term development, we hope that the company can have the ability of motorcycle engine R & D and braking system R & D. Therefore, we set up two corresponding project teams to develop the engine and braking system. In order to improve the enthusiasm of the project team, we have formulated two sets of incentive mechanisms. In this paper, we use the visiting mode to give extra cash and travel rewards to the project team that completes the task ahead of schedule or on schedule

Pattern structure

  1. State - Abstract project state
  2. Project - Abstract project
  3. FinishedAdvance - project status completed ahead of schedule
  4. Finished - project status completed on schedule
  5. BeOverdue - overdue project status
  6. ProjectA - motorcycle engine development
  7. ProjectB - Brake System Development
  8. Objectstructure - object structure

legend

Code example

<?php

namespace Visitor;

/**
 * Abstract project status
 */
abstract class State{
    protected $state;
    public abstract function getProjectAResult(Project $projectA);
    public abstract function getProjectBResult(Project $projectB);
}

//Abstract project
abstract class Project
{
    //entry name
    public $projectName;
    //Accept project status
    public abstract function Accept(State $visitor);
}
/** 
 * Early completion
 */
class FinishedAdvance extends State{
    public function __construct(){
        $this->state = "Early completion";
    }
    public function getProjectAResult(Project $projectA){
        echo "{$projectA->projectName}: Reward rules {$this->state},Give the project team a bonus of 50000 and arrange a domestic tour.<br/>";

    }
    public function getProjectBResult(Project $projectA){
        echo "{$projectA->projectName}: Reward rules {$this->state},Give 100000 bonus to the project team and arrange an overseas trip.<br/>";
    }
}
/** 
 * Completed on schedule
 */
class Finished extends State{
    public function __construct(){
        $this->state = "Completed on schedule";
    }
    public function getProjectAResult(Project $projectA){
        echo "{$projectA->projectName}: Reward rules {$this->state},Give the project team a bonus of 20000 and arrange a domestic tour.<br/>";

    }
    public function getProjectBResult(Project $projectA){
        echo "{$projectA->projectName}: Reward rules {$this->state},Give the project team a bonus of 5000 and arrange an overseas trip.<br/>";
    }
}
/**
 * be overdue
 */
class BeOverdue  extends State{
    public function __construct(){
        $this->state = "Overdue completion";
    }
    public function getProjectAResult(Project $projectA){
        echo "{$projectA->projectName}: Reward rules {$this->state},No bonus.<br/>";

    }
    public function getProjectBResult(Project $projectA){
        echo "{$projectA->projectName}: Reward rules {$this->state},No bonus.<br/>";
    }
}
//Motorcycle engine R & D project
class ProjectA extends Project
{
    function __construct()
    {
        $this->projectName="Brake R & D";
    }
 
    public  function Accept(State $visitor)
    {
        $visitor->getProjectAResult($this);
    }
}
//Research and development of braking system
class ProjectB extends Project{
    function __construct()
    {
        $this->projectName="Engine development";
    }
    public  function Accept(State $visitor)
    {
        $visitor->getProjectBResult($this);
    }
}
//Object structure
class ObjectStruct
{
    private $elements=array();
    //increase
    public function Add(Project $element)
    {
        array_push($this->elements,$element);
    }
    //remove
    public function Remove(Project $element)
    {
        foreach($this->elements as $k=>$v)
        {
            if($v==$element)
            {
                unset($this->elements[$k]);
            }
        }
    }
 
    //View display
    public function Display(State $visitor)
    {
        foreach ($this->elements as $v)
        {
            $v->Accept($visitor);
        }
    }
}
$os = new ObjectStruct();
$os->Add(new ProjectA());
$os->Add(new ProjectB());
//Response on success
$ss = new FinishedAdvance();
$os->Display($ss);
$ss = new Finished();
$os->Display($ss);
$ss = new BeOverdue();
$os->Display($ss);

Operation results

pattern analysis

  • Visitor mode is suitable for systems with relatively stable data structure. It disengages the coupling between data structure and operations acting on the structure, so that the operation set can evolve relatively freely.
  • The purpose of visitor pattern is to separate processing from data structure.
  • The advantage of visitor mode is that it is easy to add new operations, because adding new operations means adding a new visitor. Visitor mode concentrates the relevant behaviors into a visitor object. The disadvantage is that it is difficult to add new data structures.

Advantages and disadvantages

Visitor mode benefits:

  1. Visitor mode makes it easy to add new operations. Using the visitor pattern, you can add new operations without modifying the specific element class. It is mainly implemented by accepting a new visitor object through the accept method of the element class. If some operations depend on a complex structure object, generally speaking, adding new operations will be very complex. With visitor mode, adding a new operation means adding a new visitor class, so it becomes easy.

  2. Visitor pattern centralizes the relevant behaviors into one visitor object rather than scattered into node classes.

  3. The visitor pattern can access member classes belonging to different hierarchies across several class hierarchies. Iterations can only access member objects belonging to the same type hierarchy, but not objects belonging to different hierarchies. Visitor mode can do this.

  4. Accumulation state. Each individual visitor object centralizes the relevant behavior, so that the state of executing operations can be accumulated in itself in the process of access, rather than scattered among many node objects. This is an advantage for system maintenance.

Disadvantages of visitor mode

  1. Adding new node classes becomes difficult. Each addition of a new node means adding a new abstract operation to the abstract visitor role and adding corresponding concrete operations to each concrete visitor class.
  2. Destroy the package. Visitor mode requires visitor objects to access and call the operations of each node object, which implies a requirement for all node objects: they must expose some of their own operations and internal states. Otherwise, the visitor's visit will become meaningless. Because the visitor object itself will accumulate the states required for the access operation, so that these states are no longer stored in the node object, which also destroys the encapsulation.

Applicable environment

  1. An object structure contains many class objects with different interfaces, and you want to perform some operations on these objects that depend on their specific classes.
  2. You need to perform many different and irrelevant operations on objects in an object structure, and you want to avoid making these operations "pollute" the classes of these objects. The Visitor pattern allows you to centralize related operations and define them in a class.
  3. When the object structure is shared by many applications, use the Visitor mode to make each application contain only the operations that need to be used.
  4. The class that defines the object structure rarely changes, but it is often necessary to define new operations on this structure. Changing the object structure class requires redefining the interface to all visitors, which can be costly. If object structure classes change frequently, it may be better to define these operations in these classes.

Posted by mmarif4u on Fri, 17 Sep 2021 19:09:52 -0700