Visitor Pattern

  • warning: array_fill(): Number of elements must be positive in /var/www/vhosts/benjaminradtke.com/httpdocs/includes/database.inc on line 253.
  • warning: implode(): Invalid arguments passed in /var/www/vhosts/benjaminradtke.com/httpdocs/includes/database.inc on line 253.
  • warning: array_keys() expects parameter 1 to be array, null given in /var/www/vhosts/benjaminradtke.com/httpdocs/modules/user/user.module on line 528.
  • user warning: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 1 query: SELECT p.perm FROM role r INNER JOIN permission p ON p.rid = r.rid WHERE r.rid IN () in /var/www/vhosts/benjaminradtke.com/httpdocs/modules/user/user.module on line 528.
Your rating: None Average: 3 (7 votes)

Das Visitor Pattern erlaubt es eine Klasse oder auch eine ganze Objektstruktur um Funktionalitäten zu erweitern ohne diese direkt zu verändern. Die hinzukommende Logik wird im Visitor gekapselt. Die Klasse(n), welche eine Interaktion mit dem Visitor erlauben soll, muss jedoch verändert werden.

Eine beliebige Klasse Foo.

  1. class Foo {
  2.  
  3. /* eigentliche Klassenimplementation */
  4. }

Der Besucher

Eine Klasse Visitor, welche die Klasse Foo besuchen soll. Diese besitzt dazu für die zu besuchenden Klassen entsprechende Methoden visitKlassenname().

  1. class Visitor {
  2.  
  3. public function visitFoo(Foo $foo) {
  4. /* Mach was mit $foo */
  5. }
  6. }

Foo wird gastfreundlich

Die Klasse Foo wird nun um die Möglichkeit den entsprechenden Visitor zu akzeptieren erweitert.

  1. class Foo {
  2.  
  3. /* eigentliche Klassenimplementation */
  4.  
  5. public function accept(Visitor $visitor) {
  6. $visitor->visitFoo($this);
  7. }
  8. }

Der Visitor bekommt nun das zu Besuchende Objekt übergeben und kann mit diesem interagieren. Richtig interessant wird dies jedoch erst bei komplexeren Strukturen von Objekten.

Beispiel am Kompositum

Um das ganze etwas interessanter zu gestalten, könnte das Visitor Pattern anstatt einer einzelnen Klasse auch einer Objektstruktur, wie dem Composite Pattern, einen Besuch abstatten.
Um das folgende Beispiel besser zu verstehen, sollte mein Beispiel zum Composite Pattern bekannt sein.

Der Visitor wird zum Beispiel mit den Methoden für die verschiedenen Error-Klassen ausgestattet.

  1. class ErrorVisitor {
  2.  
  3. public function visitErrorLog(ErrorLog $error) {
  4. /* Mach was mit $error */
  5. }
  6.  
  7. public function visitErrorMail(ErrorMail $error) {
  8. /* ... */
  9. }
  10.  
  11. public function visitErrorSms(ErrorSms $error) {
  12. /* ... */
  13. }
  14.  
  15. public function visitErrorOutput(ErrorOutput $error) {
  16. /* ... */
  17. }
  18. }

Blätter des Kompositum erweitern

Die verschiedenen Error-Klassen bekommen jeweils eine Methode um den Visitor zu akzeptieren.

  1. class ErrorLog implements CommandInterface {
  2.  
  3. /* Eigentliche Klassenimplementation */
  4.  
  5. public function accept(ErrorVisitor $visitor) {
  6. $visitor->visitErrorLog($this);
  7. }
  8. }
  9.  
  10. class ErrorMail implements CommandInterface {
  11.  
  12. /* ... */
  13.  
  14. public function accept(ErrorVisitor $visitor) {
  15. $visitor->visitErrorMail($this);
  16. }
  17. }
  18.  
  19. /* usw. */

Kompositum erweitern

Das Kompositum bekommt ebenfalls eine Methode accept(), welche den Visitor an die registrierten Elemente weiter delegiert.

  1. class ErrorComposite implements CommandInterface {
  2.  
  3. /* Eigentliche Klassenimplementation */
  4.  
  5. public function accept(ErrorVisitor $visitor) {
  6.  
  7. foreach ($this->_errorTypes as $errorType) {
  8. $errorType->accept($visitor);
  9. }
  10. }
  11. }

Der Visitor hat nun die Möglichkeit alle Elemente der Objektstruktur des Kompositums zu durchlaufen und dessen Blätter (die Error-Objekte) aufzusuchen. Wie der Baum dabei strukturiert ist, ist für den Visitor nicht interessant, da die jeweiligen Knoten wissen, wie sie den Visitor weiter zureichen haben.

Tags