Maison >développement back-end >tutoriel php >Une introduction aux proxys virtuels, partie 2

Une introduction aux proxys virtuels, partie 2

William Shakespeare
William Shakespeareoriginal
2025-02-27 10:41:13709parcourir

An Intro to Virtual Proxies, Part 2

Points de base

  • Le proxy virtuel basé sur le polymorphisme permet une construction / chargement retardée de graphiques d'objets coûteux sans modifier le code client.
  • Les agents peuvent être conçus pour fonctionner avec un seul objet ou une collection d'objets, offrant une flexibilité et une efficacité dans la gestion des données.
  • Les agents virtuels sont particulièrement efficaces dans les collections de chargement paresseuses d'objets de domaine en stockage (par exemple, un lot d'articles de blog lorsque les commentaires pertinents peuvent être extraits de la base de données à la demande).
  • Un proxy qui simule le comportement des collections de commentaires réels est réalisé à travers un mappeur de données, améliorant ainsi la non-pertinence de la persistance.
  • Le proxy virtuel est un outil efficace pour retarder l'exécution de tâches coûteuses (par exemple, le retard de chargement de grandes quantités de données dans les niveaux de stockage) et la réduction des problèmes de rigidité et de vulnérabilité communs dans les applications orientées objet.

Le nom de l'agent virtuel semble fantaisiste, mais c'est probablement l'un des exemples les plus importants du concept de "programmation orientée vers l'interface" qui est plus qu'un simple principe dogmatique ennuyeux. Le proxy virtuel est basé sur le polymorphisme (polymorphisme dynamique, plutôt que le polymorphisme temporaire implémenté via des méthodes simples), et est un concept simple et fiable qui vous permet de retarder la construction / le chargement de graphiques d'objets coûteux sans modifier le code client. Un grand avantage des agents est qu'ils peuvent être conceptuellement conçus pour fonctionner avec un seul objet ou une collection d'objets (ou les deux, bien que cela puisse compromettre la séparation des préoccupations et est difficile à gérer au fil du temps). Pour démontrer dans une perspective pratique comment profiter des fonctionnalités fournies par un proxy virtuel, dans la première partie de cette série, j'introduis plusieurs exemples de processus de développement qui montrent comment extraire les agrégats d'une base de données en utilisant un indicateur de base pour satisfaire un modèle de domaine simple. Bien que l'expérience puisse être bénéfique et, heureusement, c'est aussi amusant, l'autre côté est un peu trompeur car il montre les tenants et aboutissants des agents virtuels, mais ne montre pas comment les mettre en œuvre dans un scénario plus réaliste. Le proxy est sans précédent en termes de collecte d'objets de domaine dans le stockage de chargement paresseux. Pour comprendre ce concept, envisagez simplement un lot de articles de blog, où chaque ensemble de commentaires connexes peut être extrait de la base de données à la demande; vous comprendrez sûrement pourquoi l'agent peut tenir ses promesses dans ce cas.

normalement, la pratique est le meilleur enseignant. Dans cette section, je vais montrer comment connecter un proxy à une collection d'objets spécifiques au domaine. Je reproduire ce scénario typique à un niveau très basique afin que vous puissiez facilement comprendre sa logique de conduite.

Créer une collection d'objets de royaume

Comme mentionné précédemment, les agents virtuels sont généralement créés lors de l'obtention de racines agrégées liées à la collection d'objets de royaume sous-jacente à partir de la couche de persistance. En raison de la nature des collections, dans de nombreux cas, la prédéfini des collections coûte cher, ce qui en fait un bon candidat pour le chargement à la demande afin de réduire les frais aller-retour de la base de données. En outre, étant donné que la relation "un-à-plusieurs" entre un article de blog et ses commentaires correspondants se reflète assez fidèlement dans ce cas d'utilisation, il serait instructif de modéliser d'abord la relation via quelques classes de domaine simples avant de traiter avec des agents spécifiques. Pour rendre les choses plus faciles à comprendre, les deux participants que j'ajouterai pendant la phase de test seront une interface isolée et un implémentateur de base. Ces deux se combinent pour définir le contrat et la mise en œuvre d'objets de blog génériques:

<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>

Comprendre la logique de la classe de post ci-dessus est un processus simple et ne nécessite pas d'explications réelles. Néanmoins, voici un détail lié notable: la classe déclare explicitement les dépendances d'une collection de commentaires qui n'ont pas été définis dans le constructeur. Créons maintenant la classe qui génère des commentaires de publication:

<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>

Jusqu'à présent, tout s'est bien passé. Outre leurs blocs minces du modèle de domaine de base, il n'y a rien à dire sur les classes de domaine ci-dessus, où chaque objet de billet de blog ouvre l'association "un à plusieurs" avec des commentaires connexes. Vous pouvez m'appeler un puriste si vous le souhaitez, mais il me semble que si la mise en œuvre actuelle du modèle n'est pas améliorée avec une collection de commentaires, il semble incomplet et maladroit. Rendre le modèle plus riche en y ajoutant ce composant supplémentaire:

<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>

Si vous regardez attentivement et parcourez le cours de commentaire de commentaire, vous remarquerez d'abord que ce n'est rien de plus qu'un emballage de tableau dénombrable itérable caché derrière le magnifique déguisement. En fait, les collections de tableaux se présentent sous de nombreuses formes et styles, mais la plupart du temps, ce ne sont que de simples usages des classes Iterator et ArrayAccess SPL. Dans ce cas, je veux me sauver (et vous) d'une tâche aussi ennuyeuse et faire de la classe l'implémenteur d'IteratorAggregate. Avec la collection de commentaires, nous pouvons aller plus loin et laisser le modèle de domaine faire ce qu'il devrait faire - opérer sur certains objets de blog, ou même les interconnecter avec un lot de commentaires avec empressement dans la base de données. Mais cela ne se trompera que sans profiter pleinement des capacités fournies par le proxy virtuel. Étant donné que dans une implémentation typique, le proxy expose la même API que l'objet de domaine réel, le proxy interagissant avec la classe de commentaire précédente devrait également implémenter le commentaire Interface afin d'adhérer au contrat avec le code client sans introduire un tas d'instructions conditionnelles problématiques.

Interaction avec les collections d'objets de domaine via des agents virtuels

Franchement, une collection de tableaux d'emballage, comme mentionné précédemment, peut exister indépendamment sans compter sur aucune autre dépendance. (Si vous êtes sceptique, n'hésitez pas à vérifier comment les collections de la doctrine fonctionnent dans les coulisses.) Pourtant, n'oubliez pas que j'essaie de mettre en œuvre un proxy qui simule le comportement d'une véritable collection d'examen, mais c'est en fait une alternative légère. La question à poser est: comment extraire les commentaires de la base de données et les mettre dans la collection précédente? Il existe plusieurs façons d'y parvenir, mais je pense que la plus attrayante est par le mappeur de données car elle améliore la non-pertinence de la persistance. Le mappeur ci-dessous rend agréable d'obtenir une collection de commentaires du stockage. Veuillez vérifier:

<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>

Bien que les chercheurs exposés par la classe COMMENTMAPPER s'en tiennent généralement à l'API qui pourraient être attendus dans les implémentations de mappeurs de données standard, la méthode Fetchall () est de loin la méthode la plus convaincante. Il extrait d'abord tous les articles de blog des commentaires du stockage et les met dans la collection, et renvoie enfin la collection au code client. Si vous êtes comme moi, vous pouvez avoir un réveil dans votre esprit car la collection est instanciée directement à l'intérieur de la méthode. En fait, il n'est pas nécessaire de paniquer à propos de nouveaux opérateurs qui se faufilaient en dehors de l'usine, du moins dans ce cas, car la collection est en fait une structure générale qui relève de la catégorie "créée", plutôt que de la catégorie "injectable". Quoi qu'il en soit, n'hésitez pas à le faire si vous vous sentez un peu moins coupable en injectant la collection dans le constructeur du mappeur. Avec le mappeur de commentaires, il est temps de découvrir la véritable épiphanie et de construire une classe de procuration qui intervient avec l'ensemble précédent:

<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>

Comme vous pouvez vous y attendre, CommentCollectionProxy implémente la même interface qu'une collection de vrais commentaires. Cependant, sa méthode getcomments () fait le travail réel dans les coulisses et retarde le chargement des commentaires de la base de données via le mappeur passé dans le constructeur. Cette méthode simple et efficace vous permet de faire toutes sortes d'actions intelligentes sur vos commentaires sans surclassement. Voulez-vous voir quelles méthodes souhaitez-vous voir? Supposons que vous deviez faire lier tous les commentaires à un article de blog spécifique de la base de données. L'extrait de code suivant peut le faire:

<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>

L'inconvénient de cette approche est que les commentaires sont d'abord extraits du stockage puis injectés à l'intérieur de l'objet post. Comment le faire l'inverse, mais cette fois, c'est pour «parcourir» le code client avec un proxy?

<code class="language-php"><?php namespace ModelCollection;

interface CommentCollectionInterface extends Countable, IteratorAggregate
{
    public function getComments();
}</code>

Les commentaires retardent non seulement le chargement de la base de données de la base de données après le proxy dans la boucle Foreach, mais l'API exposée au code client maintient sa structure d'origine inchangée tout au long du processus. Onelons-nous même demander quelque chose de mieux? À moins que vous ne soyez très gourmand, il est difficile pour moi de le penser. Dans les deux cas, vous devez comprendre la réalité dans les coulisses de l'agent virtuel et comment tirer le meilleur parti de ses capacités d'amélioration de l'efficacité opérationnelle de l'objet de domaine et de la couche de persistance sous-jacente.

Conclusion

Bien qu'il soit simple, surtout si vous êtes assez audacieux pour l'utiliser dans un environnement de production, l'exemple précédent montre brièvement des concepts intéressants. Premièrement, les agents virtuels sont non seulement faciles à configurer et à utiliser, mais sont sans précédent pour mélanger différentes implémentations au moment de l'exécution pour retarder la réalisation de tâches coûteuses (par exemple, retardant le chargement de grandes quantités de données dans le niveau de stockage ou créant des graphiques d'objets poids lourds). Deuxièmement, ce sont des exemples classiques de la façon dont les polymorphismes peuvent devenir des vaccins efficaces qui réduisent les problèmes de rigidité et de vulnérabilité communs dont souffrent de nombreuses applications orientées objet. De plus, comme le modèle d'objet de PHP est simple et prend en charge les fermetures, il est possible de mélanger intelligemment ces fonctionnalités et de créer un proxy dont la logique sous-jacente est motivée par les avantages des fermetures. Si vous voulez relever ce défi vous-même, je vous souhaite tout le meilleur à l'avance.

(image d'Imredesiuk / Shutterstock)

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn