Stellvertreter

Problem

Der Zugriff auf ein Objekt soll durch ein vorgelagertes Stellvertreterobjekt kontrolliert werden.

Motivation

Funktionalität wie beispielsweise Zugriffskontrolle, die Verzögerung von Berechnungen, oder das Vorhalten von bereits berechneten Ergebnissen möchte man in einer eigenen Klasse modellieren. Ein Objekt dieser Klasse wird als Stellvertreter für ein anderes Objekt verwendet.

Lösung

Die beiden Klassen, von denen die Objekte der einen Objekte der anderen vertreten sollen, implementieren dieselbe Schnittstelle. Über den Konstruktor erhält das Stellvertreterobjekt eine Referenz auf das zu vertretende Objekt, um Methodenaufrufe gegebenfalls an dieses delegieren zu können.

Anwendungsbeispiele

Durch die Vorlagerung eines Stellvertreterobjektes kann bei einem Methodenaufruf entschieden werden, ob der unter Umständen teure Aufruf der Methode des eigentlichen Objektes überhaupt ausgeführt werden muss. Wird die Methode zum wiederholten Male mit demselben Parameter aufgerufen, und liefert die Methode für identische Parameter immer dasselbe Ergebnis, so kann die wiederholte Ausführung durch Speicherung des Ergebnisses vermieden werden.

Beispiel 6.4 und Beispiel 6.5 zeigen eine Schnittstelle TeureBerechnung und mit Beispiel eine entsprechende Implementierung.

Beispiel 6.4: Die Schnittstelle TeureBerechnung

<?php
interface TeureBerechnung {
  public function rechne($a);
}
?>


Beispiel 6.5: Die Klasse Beispiel

<?php
class Beispiel implements TeureBerechnung {
  public function rechne($a) {
    // ...
  }
}
?>


Die Klasse BeispielStellvertreter (Beispiel 6.6) implementiert ebenfalls die Schnittstelle TeureBerechnung. Darüber hinaus bietet sie jedoch einen Caching-Mechanismus, der das Ergebnis der Methodenaufrufe von rechne($a) speichert und so die wiederholte Berechnung für gleiche Parameter $a verhindert.

Beispiel 6.6: Die Klasse BeispielStellvertreter

<?php
class BeispielStellvertreter implements TeureBerechnung {
  private $cache = array();
  private $objekt;
 
  public function __construct(TeureBerechnung $objekt) {
    $this->objekt = $objekt;
  }
 
  public function rechne($a) {
    if (!isset($this->cache[$a])) {
      $this->cache[$a] = $this->objekt->rechne($a);
    }
 
    return $this->cache[$a];
  }
}
?>


Das Stellvertreter-Muster spielt in der verteilten Programmierung ebenfalls eine Rolle. So werden beispielsweise die über einen Webdienst (siehe Kapitel 9) angebotenen Methoden auf der Client-Seite von einem Stellvertreter-Objekt repräsentiert.

In ihrer Implementierung ähneln sich die Entwurfsmuster Dekorierer (siehe „Dekorierer“) und Stellvertreter. Der Unterschied zwischen diesen beiden Mustern liegt im Ziel, das sie verfolgen. Ein Dekorierer wird genutzt, um die Funktionalität eines bestehenden Objektes zu erweitern oder zu verändern, während ein Stellvertreter den Zugriff auf das bestehende Objekt kontrolliert.