Tag Archive for 'php visitor pattern'

PHP Visitor Design Pattern II: The Double Dispatch

visitor2x

The Visitor pattern uses a double dispatch even with languages that are inherently single dispatch (such as PHP). In this second installment of the Visitor, I’d like to look at the concept and utility of double dispatch and role of the ObjectStructure in creating a working Visitor example that can be transformed into a practical application.

In Part I PHP Visitor Design Pattern I: The Single Dispatch, the focus was on using a single dispatch and a “pretend visitor.” This post shows how to create a visitor object based on both a Visitor interface and ConcreteVisitor implementations that are used in concert with the Element participants via the ObjectStructure. In order to do this, a couple more concrete Elements have been added to the example begun in Part I of the Visitor.

The Visitor Design Pattern Diagram

The Part I Visitor post suggests that the Visitor class diagram is a bit daunting, and so I held off until now to show it. If you look at the bottom portion of Figure 1, you will see that the example in Part I handled all of the Element participants, and included a “pretend visitor” where the Accept(Visitor) implementation in an actual Visitor pattern goes. So, you have some idea of what close to half of the Visitor does.

Figure 1: Visitor Class Diagram

Figure 1: Visitor Class Diagram

You can get a hint at what double-dispatch is by looking at the dual connections that the Client has to both the Visitor and Element (via the ObjectStructure). In the pattern, the Client is implied, but it’s clear to see the double reference to both the Visitor and the ObjectStructure which holds a reference to the Element.

This particular implementation of the Visitor pattern extends the example used in Part I where a “pretend” visitor is an operation that provides the fill color of SVG images. In this implementation, the fill color operation is provided by an actual visitor object. A third and forth Element class have been added, one with a visitor (Triangle) and one that does not have a visitor (zigzag lines have no fill colors—just a stroke color.) Figure 2 shows the program as a file diagram:

Figure 2: File diagram of Visitor pattern in PHP

Figure 2: File diagram of Visitor pattern in PHP

To get an idea of what the application does and look at the overall code, run the program and download the files:
PlayDownload

When you run the program, you can see that the shape (concrete Element) and the color (concrete Visitor) are selected separately. Those separate selections are to highlight the concept of double-dispatch. A shape and color are selected with the understanding that the developer had not included a fill color originally, and instead of starting from scratch to re-program the shape selector, the developer added a visitor. To see how double-dispatch works in a Visitor pattern, follow the path from the Client to the ObjectStructure and to the IElement::accept() method.

Double-Dispatch and Traversing Elements with Visitors

Figure 3: ObjectStructure and IElement::accept() double-dispatch link

Figure 3: ObjectStructure and IElement::accept() double-dispatch link

One of the key participants in the Visitor pattern is the ObjectStructure class. The Gang of Four introduce the ObjectStructure participant to handle traversing the Element objects that may need the attention of a Visitor. The pattern solves the double-dispatch problem by including a concrete visitor in the Element::accept(IVisitor) method. However, the path from Client-request to double-dispatch first goes through the ObjectStructure class. By looking the Client, ObjectStructure and a concrete Element, you can see the double-dispatch process:

< ?php
/*
* CLIENT
*/
//Client.php
error_reporting(E_ALL | E_STRICT);
ini_set("display_errors", 1);
//Autoload code
function includeAll($className)
{
    include_once($className . '.php');
}
spl_autoload_register('includeAll');
 
//Begin Client class
class Client
{
    private static $shapeElement;
    private static $color;
    //client request
    public static function request()
    {
      self::$shapeElement=$_POST['shape'];
      self::$color=$_POST['color'];
 
      $obStructure = new ObjectStructure();
      $obStructure->attach(new self::$shapeElement());
      $colorVisitor= new self::$color();
      echo $obStructure->confirm($colorVisitor);
    } 
}
Client::request();
?>
 
 
< ?php
/*
* OBJECT STRUCTURE
*/
//ObjectStructure.php
class ObjectStructure
{
    private $elements=array();
 
    public function attach(IElement $element)
    {
         array_push($this->elements,$element);
    }
 
    public function confirm(IVisitor $visitor)
    {
         foreach($this->elements as $elementNow)
         {
              return $elementNow->accept($visitor);
         }
    }
}
?>
 
 
< ?php
/*
* ELEMENT
*/
//Circle.php
class Circle implements IElement
{
    private $visColor;
 
    public function accept(IVisitor $visitor)
    {
        $visitor->visitCircle($this);
        return $this->showShape();
    }
 
    private function showShape()
    {
        $circleShape= IElement::SVG . "<circle cx='110' cy='110' r='100' fill='{$this->doColor()}' stroke='blue' stroke-width='1' />";
        return $circleShape;
    }
 
    public function setColor($visitorColor)
    {
         $this->visColor = $visitorColor;
    }
 
    private function doColor()
    {
        return $this-> visColor;
    }
}
?>
 
</circle>

Stepping through the process, the Client first (1) instantiates an instance of ObjectStructure. Second (2) the Client uses the ObjectStructure::attach() method to push the selected element instance onto an array. Third (3) the Client passes the selected visitor to the ObjectStructure::confirm() method, which in turn, fourth (4) calls the Element::accept($v) method which passes the concrete visitor to all of the elements in the array. Since this example is very simple, it only includes one element and one visitor at a time, and so the array will only contain a single element. However, because of the ObjectStructure class, you can add more elements if needed. (The following sections show more detail on how double-dispatch works and how the visitors are implemented.)
Continue reading ‘PHP Visitor Design Pattern II: The Double Dispatch’

Share