Heim >Backend-Entwicklung >PHP-Tutorial >Ein Intro in virtuelle Proxies, Teil 2
Kernpunkte
Der Name des virtuellen Agenten klingt schick, aber es ist wahrscheinlich eines der bekanntesten Beispiele für das Konzept der "interface-orientierten Programmierung", das mehr als nur ein langweiliges dogmatisches Prinzip ist. Virtual Proxy basiert auf Polymorphismus (dynamischer Polymorphismus und nicht auf temporärem Polymorphismus, der durch einfache Methoden implementiert wird) und ist ein einfaches und zuverlässiges Konzept, mit dem Sie das Erstellen/Laden kostspieliger Objektdiagramme verzögern können, ohne den Client -Code zu ändern. Ein großer Vorteil von Agenten besteht darin, dass sie konzeptionell so konzipiert werden können, dass sie mit einem einzelnen Objekt oder einer Sammlung von Objekten arbeiten (oder beides, obwohl dies dies tut, die die Trennung von Bedenken gefährden und im Laufe der Zeit schwer zu verwalten sind). Um aus einer praktischen Perspektive zu demonstrieren, wie die Funktionen eines virtuellen Proxy im ersten Teil dieser Serie ausnutzen können, stelle ich mehrere Beispielentwicklungsprozesse ein, die zeigen, wie Aggregate aus einer Datenbank mithilfe eines Basis -Proxy extrahiert werden, um ein einfaches Domänenmodell zu erfüllen. Während die Erfahrung vorteilhaft sein kann und zum Glück auch Spaß macht, ist die andere Seite etwas täuschend, da sie die Vor- und Nachteile virtueller Agenten zeigt, aber nicht zeigt, wie sie in einem realistischeren Szenario umgesetzt werden können. Der Proxy ist in Bezug auf die Sammlung von Domänenobjekten im faulen Ladenspeicher beispiellos. Um dieses Konzept zu verstehen, berücksichtigen Sie einfach eine Reihe von Blog -Posts, bei denen jede Reihe von verwandten Kommentaren aus der Datenbank auf Demand extrahiert werden kann.
Normalerweise ist Praxis der beste Lehrer. In diesem Abschnitt werde ich zeigen, wie Sie einen Proxy mit einer Sammlung von domänenspezifischen Objekten verbinden. Ich werde dieses typische Szenario auf einer sehr grundlegenden Ebene reproduzieren, damit Sie seine treibende Logik leicht verstehen können.
Erstellen Sie eine Sammlung von Realm -Objekten
Wie bereits erwähnt, werden virtuelle Agenten normalerweise erstellt, wenn aggregierte Wurzeln aus der Persistenzschicht an die zugrunde liegende Realm -Objektsammlung erhalten werden. Aufgrund der Art von Sammlungen ist in vielen Fällen die Vorbereitung von Sammlungen teuer, was sie zu einem guten Kandidaten für das Laden von Bedarf zur Reduzierung der Datenbank-Roundreise für die Aufwand für die Datenbank macht. In Anbetracht der Tatsache, dass die Beziehung zwischen einem Blog-Beitrag und seinen entsprechenden Kommentaren in diesem Anwendungsfall sehr gut widerspiegelt, wäre es aufschlussreich, die Beziehung zuerst durch einige einfache Domänenklassen zu modellieren, bevor es sich mit bestimmten Agenten befasst. Um die Dinge zu verstehen, werden die beiden Teilnehmer, die ich während der Testphase hinzufügen werde, eine isolierte Schnittstelle und ein grundlegender Implementierer sein. Diese beiden kombinieren den Vertrag und die Implementierung generischer Blog -Post -Objekte:
<code class="language-php"><?php namespace Model; use ModelCollectionCommentCollectionInterface; interface PostInterface { public function setId($id); public function getId(); public function setTitle($title); public function getTitle(); public function setContent($content); public function getContent(); public function setComments(CommentCollectionInterface $comments); public function getComments(); }</code>
<code class="language-php"><?php namespace Model; use ModelCollectionCommentCollectionInterface; class Post implements PostInterface { protected $id; protected $title; protected $content; protected $comments; public function __construct($title, $content, CommentCollectionInterface $comments = null) { $this->setTitle($title); $this->setContent($content); $this->comments = $comments; } // ... (Post class methods remain largely unchanged) ... }</code>
Die Logik der obigen Postklasse verstehen, ist ein einfacher Prozess und erfordert keine echte Erklärung. Hier finden Sie jedoch ein bemerkenswertes Detail: Die Klasse erklärt Abhängigkeiten ausdrücklich zu einer Sammlung von Kommentaren, die im Konstruktor nicht definiert wurden. Erstellen wir nun die Klasse, die Post -Kommentare generiert:
<code class="language-php"><?php namespace Model; interface CommentInterface { public function setId($id); public function getId(); public function setContent($content); public function getContent(); public function setPoster($poster); public function getPoster(); }</code>
<code class="language-php"><?php namespace Model; class Comment implements CommentInterface { protected $id; protected $content; protected $poster; public function __construct($content, $poster) { $this->setContent($content); $this->setPoster($poster); } // ... (Comment class methods remain largely unchanged) ... }</code>
Bisher lief alles gut. Abgesehen von ihren dünnen Blöcken des grundlegenden Domänenmodells gibt es nichts über die oben genannten Domänenklassen zu sagen, in denen jedes Blog-Post-Objekt die "Eins-zu-Viele-Assoziation" mit verwandten Kommentaren öffnet. Sie können mich einen Puristen nennen, wenn Sie möchten, aber es scheint mir, dass die aktuelle Implementierung des Modells nicht mit einer Sammlung von Kommentaren verbessert wird, es unvollständig und ungeschickt aussieht. Lassen Sie uns das Modell reicher machen, indem wir diese zusätzliche Komponente dazu hinzufügen:
<code class="language-php"><?php namespace ModelCollection; interface CommentCollectionInterface extends Countable, IteratorAggregate { public function getComments(); }</code>
<code class="language-php"><?php namespace ModelCollection; use ModelCommentInterface; class CommentCollection implements CommentCollectionInterface { protected $comments = array(); public function __construct(array $comments = array()) { // ... (CommentCollection class methods remain largely unchanged) ... } }</code>
Wenn Sie sorgfältig schauen und in der Kommentarklasse durchsuchen, werden Sie zunächst feststellen, dass es nichts anderes als ein iterabler, zählbarer Array -Wrapper ist, der hinter der wunderschönen Verkleidung versteckt ist. Tatsächlich gibt es Array -Sammlungen in vielen Formen und Stilen, aber die meiste Zeit sind sie nur einfache Verwendung von Iterator- und ArrayAccess -SPL -Klassen. In diesem Fall möchte ich mich (und Sie) vor einer so langweiligen Aufgabe retten und die Klasse zum Implementierer von Iteratoraggregate machen. Mit der Kommentarsammlung können wir noch einen Schritt weiter gehen und das Domänenmodell tun lassen, was es tun sollte - in einigen Blog -Postobjekten oder sogar mit einer Reihe von Kommentaren miteinander verbunden sind, die eifrig aus der Datenbank abgerufen werden. Aber dies wird uns nur täuschen, ohne die Fähigkeiten des virtuellen Proxy voll auszunutzen. In Anbetracht der Tatsache, dass der Proxy in einer typischen Implementierung dieselbe API wie das reale Domänenobjekt enthält, sollte der Proxy, der mit der vorherigen Kommentarklasse interagiert, auch die commentCollectionInterface implementieren, um den Vertrag mit dem Client -Code zu halten, ohne eine Reihe problematischer bedingter Anweisungen einzuführen.
Interaktion mit Sammlungen von Domänenobjekten durch virtuelle Agenten
ehrlich gesagt kann eine Sammlung von Wickelarrays, wie bereits erwähnt, unabhängig existieren, ohne sich auf andere Abhängigkeiten zu verlassen. (Wenn Sie skeptisch sind, können Sie überprüfen, wie Sammlungen in der Doktrin hinter den Kulissen funktionieren.) Denken Sie jedoch daran, dass ich versuche, einen Proxy zu implementieren, der das Verhalten einer realen Überprüfungssammlung simuliert, aber es ist tatsächlich eine leichte Alternative. Die Frage stellt: Wie extrahieren Sie Kommentare aus der Datenbank und setzen sie in die vorherige Sammlung ein? Es gibt verschiedene Möglichkeiten, dies zu erreichen, aber ich denke, der attraktivste ist der Data Mapper, weil es die Irrelevanz der Persistenz verbessert. Der Mapper unten macht es schön, eine Sammlung von Kommentaren aus dem Speicher zu erhalten. Bitte überprüfen Sie:
<code class="language-php"><?php namespace Model; use ModelCollectionCommentCollectionInterface; interface PostInterface { public function setId($id); public function getId(); public function setTitle($title); public function getTitle(); public function setContent($content); public function getContent(); public function setComments(CommentCollectionInterface $comments); public function getComments(); }</code>
<code class="language-php"><?php namespace Model; use ModelCollectionCommentCollectionInterface; class Post implements PostInterface { protected $id; protected $title; protected $content; protected $comments; public function __construct($title, $content, CommentCollectionInterface $comments = null) { $this->setTitle($title); $this->setContent($content); $this->comments = $comments; } // ... (Post class methods remain largely unchanged) ... }</code>
Während die Finder, die von der Kommentarklasse ausgesetzt sind, normalerweise an der API haften, die bei Standarddaten -Mapper -Implementierungen zu erwarten ist, ist die Methode Fetchall () bei weitem die überzeugendste Methode. Es extrahiert zunächst alle Blog -Post -Kommentare aus dem Speicher und versetzt sie in die Sammlung und gibt die Sammlung schließlich in den Client -Code zurück. Wenn Sie wie ich sind, haben Sie möglicherweise einen Weckruf im Kopf, da die Sammlung direkt in der Methode instanziiert ist. In der Tat besteht keine Notwendigkeit, über neue Betreiber außerhalb der Fabrik in Panik zu geraten, zumindest in diesem Fall, da die Sammlung tatsächlich eine allgemeine Struktur ist, die in die Kategorie "erstellt" und nicht in die Kategorie "injizierbar" fällt. Wie auch immer, tun Sie es gerne, wenn Sie sich etwas weniger schuldig fühlen, indem Sie die Sammlung dem Konstruktor des Mapper injizieren. Mit dem Kommentar Mapper ist es Zeit, die echte Offenbarung zu erleben und eine Proxy -Klasse zu erstellen, die sich mit dem vorherigen Satz vermittelt:
<code class="language-php"><?php namespace Model; interface CommentInterface { public function setId($id); public function getId(); public function setContent($content); public function getContent(); public function setPoster($poster); public function getPoster(); }</code>
Wie Sie vielleicht erwarten, implementiert CommentCollectionProxy dieselbe Schnittstelle wie eine Sammlung realer Kommentare. Die Methode von GetComentment () führt jedoch die tatsächliche Arbeit hinter den Kulissen durch und verzögert das Laden von Kommentaren aus der Datenbank über den im Konstruktor übergebenen Mapper. Mit dieser einfachen und effektiven Methode können Sie alle Arten von cleveren Aktionen auf Ihre Kommentare ausführen, ohne zu überarbeiten. Möchten Sie sehen, welche Methoden Sie sehen möchten? Angenommen, Sie müssen alle Kommentare an einen bestimmten Blog -Beitrag aus der Datenbank gebunden lassen. Das folgende Code -Snippet kann dies tun:
<code class="language-php"><?php namespace Model; class Comment implements CommentInterface { protected $id; protected $content; protected $poster; public function __construct($content, $poster) { $this->setContent($content); $this->setPoster($poster); } // ... (Comment class methods remain largely unchanged) ... }</code>
Der Nachteil dieses Ansatzes besteht darin, dass die Kommentare zuerst aus dem Speicher extrahiert und dann in die Innere des Postobjekts injiziert werden. Wie geht es umgekehrt, aber diesmal ist es, den Client -Code mit einem Proxy zu "fälschen"?
<code class="language-php"><?php namespace ModelCollection; interface CommentCollectionInterface extends Countable, IteratorAggregate { public function getComments(); }</code>
Kommentare verzögern nicht nur transparent das Laden aus der Datenbank, nachdem der Proxy in die Foreach -Schleife platziert wurde, sondern die dem Client -Code ausgesetzte API hält seine ursprüngliche Struktur während des gesamten Prozesses unverändert. Wagen wir es uns überhaupt, nach etwas Besserem zu fragen? Wenn Sie nicht sehr gierig sind, fällt es mir schwer, das zu denken. In beiden Fällen sollten Sie die Realität hinter den Kulissen des virtuellen Agenten verstehen und wie Sie ihre Fähigkeiten zur Verbesserung der betrieblichen Effizienz des Domänenobjekts und der zugrunde liegenden Persistenzschicht optimal nutzen können.
Schlussfolgerung
Während es einfach ist, insbesondere wenn Sie mutig genug sind, es in einer Produktionsumgebung zu verwenden, zeigt das vorherige Beispiel kurz einige interessante Konzepte. Erstens sind virtuelle Agenten nicht nur einfach einzurichten und zu verwenden, sondern auch bei der Mischung verschiedener Implementierungen zur Laufzeit bei der Ausführung teurer Aufgaben (z. B. Verzögerung des Ladens großer Datenmengen in der Speicherstufe oder Erstellen von Schwergewichts -Objektdiagrammen). Zweitens sind sie klassische Beispiele dafür, wie Polymorphismen wirksame Impfstoffe werden können, die gemeinsame Starrheit und Anfälligkeitsprobleme reduzieren, unter denen viele objektorientierte Anwendungen leiden. Da das Objektmodell von PHP einfach ist und Verschlüsse unterstützt, ist es möglich, diese Merkmale geschickt zu mischen und einen Stellvertreter zu erstellen, dessen zugrunde liegende Logik durch die Vorteile von Schließungen angetrieben wird. Wenn Sie sich selbst mit dieser Herausforderung umgehen möchten, wünsche ich Ihnen alles Gute im Voraus.
(Bild von Imredesiuk / Shutterstock)
Das obige ist der detaillierte Inhalt vonEin Intro in virtuelle Proxies, Teil 2. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!