Visitor (design sample)
The Visitors ( English visitor or visitor pattern ) is a design pattern in the field of software development , which the category of behavioral patterns (Engl. Behavioral patterns ) belongs. The pattern is one of the so-called GoF design patterns . It is used to encapsulate operations that, when carried out on elements of an object structure, enable new operations to be defined without changing the element classes concerned.
With the help of the visitor, simple multi- methods ( double dispatch ) are implemented in an OOP language that only supports single dispatch by default .
use
The integration of various unrelated operations into the classes of an object structure is often difficult. When adding new operations, all classes must be extended. The visitor outsources the operations to external visitor classes. To do this, however, the classes to be visited must define an interface for receiving a visitor.
Generally recommended to use visitors when
- many different, unrelated operations are to be implemented on an object structure,
- the classes of the object structure do not change,
- often new operations have to be integrated on the object structure or
- an algorithm works distributed across the classes of an object structure, but should be managed centrally.
UML diagram
actors
- Visitor (abstract)
- declares a visit function for each class of concrete elements
- Visitor1, ... (specifically)
- implements visiting functions
- Each visit function is part of the algorithm that is applied to the entire object structure.
- Local state serves as the context for the algorithm.
- Element (abstract)
- declares an operation to receive a visitor
- ElementA, ... (concrete)
- implements the reception of a visitor
- Object structure
- Collection or compound object structure (see compound word (design sample) )
advantages
- New operations can be easily added by defining new visitors.
- Related operations are centrally managed in the visitor and separated from non-visitor operations.
- Visitors can work with objects from independent class hierarchies.
disadvantage
- The good expandability of the classes of visitors has to be bought with a poor expandability of the classes of the concrete elements. If new concrete elements have to be added, this means that many visitor visit methods have to be implemented.
Examples
Virtual travel agency
A tour operator offers its customers various bus trips, holiday homes and rental cars. A description and a price category for summer and winter are assigned to each property. The prices of the categories are stored in a price module. In addition, pictures are stored for holiday homes and technical data for rental cars. The classes for bus trips, holiday homes and rental cars as well as the price module offer an interface for receiving a visitor. The price module is outside the class hierarchy of bus trips, vacation homes and rental cars.
A customer can now put together a trip. If he then asks about the total price, a visitor first visits the objects of interest and asks about the respective category. He manages a local meter for each category. Finally, he visits the price module and calculates the total price based on the prices stored there and the information he has collected locally.
If the customer decides to book the trip, another visitor can create a travel confirmation. To do this, he visits the objects that interest the customer and the price module. Its local state consists of a document that it designs according to the information from the objects. For all objects it first lists the description and the price category, and for rental cars it also lists the technical data. When visiting the price module, he then adds the specific prices to the individual descriptions.
Both visitors overlap class hierarchies, as they work both on the class hierarchy of the bookable travel elements and on the price module.
Visitors in the compiler construction
In compiler construction , after the syntactic analysis, there is usually an abstract syntax tree . Such a tree can be easily described as an object structure using classes for the various elements and the use of aggregations . On this object structure you can now define a general visitor who traverses the tree . For this purpose, when the visit function is implemented for an element class of the tree, the aggregated elements are visited one after the other. From this general visitor, various visitors can now be derived who implement different operations on the abstract syntax tree.
The semantic analysis can be implemented in a visitor. To do this, it visits the elements of the tree and extends the symbol table with information on the data types of variables and routines or checks expressions, including the symbol table, to see whether they are well-typed. Depending on the properties of the source language, the collection of information and the type check must also be distributed between two visitors.
Another visitor can then carry out the synthesis of the target code. This also visits the individual elements and collects the target code fragments in its local state. Depending on the class of the element visited, he can then combine fragments that have already been collected into larger ones.
Additional visitors can collect debug information or perform code optimizations on a source code basis. All visitors can use the visit functions of the general visitor if an element is only to be traversed without further operations. The target code can also initially be generated in a tree structure in order to then implement various optimizations in different visitors.
Programming example in PHP
abstract class Element {
abstract function entgegennehmen(Besucher $besucher);
abstract function getName();
}
class ElementA extends Element {
private $info_A;
public function __construct($text1, $text2) {
$this->info_A = '['.$text1.'--'.$text2.']';
}
public function getName() {
return 'A';
}
public function getInfo() {
return $this->info_A;
}
public function entgegennehmen(Besucher $besucher) {
$besucher->BesuchVonElementA($this);
}
}
class ElementB extends Element {
private $the_data;
public function __construct($text) {
$this->the_data = '('.$text.')';
}
public function getName() {
return 'B';
}
public function getData() {
return $this->the_data;
}
public function entgegennehmen(Besucher $besucher) {
$besucher->BesuchVonElementB($this);
}
}
abstract class Besucher {
abstract function BesuchVonElementA(ElementA $elem);
abstract function BesuchVonElementB(ElementB $elem);
}
class Besucher1 extends Besucher {
private $characteristics;
public function getCharacs() {
return $this->characteristics;
}
public function BesuchVonElementA(ElementA $elem) {
$this->characteristics = 'Info:'.$elem->getInfo();
}
public function BesuchVonElementB(ElementB $elem) {
$this->characteristics = 'DATA:'.$elem->getData().'!!';
}
}
function Test() {
write_line('Testanfang');
// Objektstruktur
$elemente = array (
new ElementA('Hallo', 'Neu!!'),
new ElementB('Endlich.'),
);
$bes1 = new Besucher1();
foreach ($elemente as $element) {
$element->entgegennehmen($bes1);
write_line('Nach Besuch von Element '.$element->getName().': '.$bes1->getCharacs());
}
}
function write_line($text) {
print $text.'<br/>';
}
Test();
Output:
Testanfang Nach Besuch von Element A: Info:[Hallo--Neu!!] Nach Besuch von Element B: DATA:(Endlich.)!!
Related design patterns
- Command . Like the visitor, the command encapsulates one or more functions in an object in order to deliver them to a caller. In contrast to the visitor, the command does not contain any principle for traversing an object structure.
- Iterator . The iterator defines a traversal principle like the visitor, but does not differentiate between types of the traversed objects.
Relationship to other design patterns
- Compound word . If the types are defined in a sufficiently stable manner in a composite structure, a visitor can be used to edit the structure.
Individual evidence
- ↑ Erich Gamma , Richard Helm , Ralph Johnson , John Vlissides : Design pattern . 5th edition. Addison-Wesley , 1996, ISBN 3-8273-1862-9 , pp. 301 .