Maison  >  Article  >  développement back-end  >  Conteneur d'injection de dépendances PHP facile à comprendre

Conteneur d'injection de dépendances PHP facile à comprendre

silencement
silencementavant
2020-01-19 17:54:333529parcourir

Conteneur d'injection de dépendances PHP facile à comprendre

Compréhension du conteneur d'injection de dépendances

Couplage

Une bonne conception de structure de code doit être faiblement couplée, ce qui est également l'objectif de nombreux modèles de conception courants. Il s'agit de rassembler les codes d'une même fonction dispersés partout pour former un module, puis de communiquer entre différents modules à travers des canaux petits et clairs.

En pratique, l'interdépendance entre les différentes fonctions et modules est inévitable, et la façon de gérer la relation entre ces dépendances est la clé pour savoir si la structure du code peut devenir belle.

<?php
class User
{
    public function register($user)
    {
        // 注册操作
        ...
 
        // 发送确认邮件
        $notify = new Notify();
        $notify->sendEmail(&#39;register&#39;, $user);
    }
}
 
class Notify
{
    public function sendEmail($type, $data)
    {
        switch $type {
            case &#39;register&#39;:
                // 发送注册确认邮件
                $email = new Email($type);
                $email->send($data);
            ...
        }
    }
}
 
class Email
{
    public function send($data)
    {
        // 发送邮件
    }
}

Dans le code ci-dessus, il existe des dépendances couche par couche entre les trois classes. L'ordre d'instanciation des trois classes est User -> Email

That. c'est-à-dire que j'instancie d'abord. La classe User peut exécuter du code, puis instancier d'autres classes dont j'ai besoin, telles que Notify, etc.

Ce type de dépendance nous obligera à faire un travail de préparation afin d'obtenir les dépendances requises. Parfois, une nouvelle opération peut ne pas suffire. Cette partie du travail est appelée couplage, qui oblige une classe dotée de fonctions indépendantes à se soucier de certaines opérations qui n'ont rien à voir avec sa fonction principale.

Supprimer la dépendance d'une classe vis-à-vis d'autres classes

Il est également très simple de résoudre ce problème. Je peux d'abord instancier la classe Email, puis instancier Notify, puis transmettre l'objet Email en tant que. un paramètre To Notify, instanciez enfin la classe User, puis transmettez Notify. C'est ce qu'on appelle l'injection de dépendances. Vous pouvez voir que l'ordre d'instanciation de classe dans ce processus est complètement inversé. L'objet dépendant est instancié en premier, plutôt que l'objet final requis.

Le code est le suivant :

<?php
$email = new Email();
$notify = new Notify($email);
$user = new User($notify);

Vous pouvez injecter les dépendances requises via le constructeur, ou vous pouvez utiliser d'autres méthodes.

Utiliser un conteneur pour héberger les dépendances

Ensuite, il y a un nouveau problème. Dans l'exemple, il n'y a que trois classes. Ensuite, si la classe User dépend de Notify. envoyer des e-mails, le modèle de dépendance stocke la base de données et s'appuie sur Redis pour la mise en cache. Bien que cela transfère la dépendance en dehors de la classe, cela m'oblige toujours à effectuer beaucoup de travail de préparation manuelle lorsque je souhaite simplement instancier l'utilisateur, ce qui rend le code déroutant. . Un conteneur est donc nécessaire à ce moment-là. Le rôle de ce conteneur est de gérer ces dépendances pour moi.

<?php
// 容器
class Container implements ArrayAccess
{
    protected $values = [];
 
    public function offsetGet($offset) 
    {
        return $this->values[$offset]($this);
    }
 
    public function offsetSet($offset, $value) 
    {
        $this->values[$offset] = $value;
    }
}

Lorsque le programme démarre, nous pouvons enregistrer une série de services de base en un seul endroit.

<?php
$container = new Container();
 
$container[&#39;notify&#39;] = function($c) {
    return new Notify();
};
 
$container[&#39;email&#39;] = function($c) {
    return new Email();
};

deviendra comme ceci

<?php
class User
{
    public function register($user)
    {
        // 注册操作
        ...
 
        // 发送确认邮件
        $container(&#39;notify&#39;)->sendEmail(&#39;register&#39;, $user);
    }
}
 
class Notify
{
    public function sendEmail($type, $data)
    {
        switch $type {
            case &#39;register&#39;:
                // 发送注册确认邮件
                $email = $container[&#39;email&#39;];
                $email->send($data);
            ...
        }
    }
}
 
class Email
{
    public function send($data)
    {
        // 发送邮件
    }
}

C'est-à-dire que lorsque l'utilisateur aura besoin de Notify, il demandera au conteneur un objet de cette classe. Quant aux autres choses dont dépend Notify, je ne le fais pas. Vous n'avez pas à vous en soucier, car Notify demandera également au conteneur les dépendances dont il a besoin. Le traitement de toutes ces dépendances est entièrement géré par le conteneur. Nous n'avons pas besoin de nous soucier de la relation hiérarchique entre les dépendances ni d'éviter le couplage entre les dépendances.

Il est à noter que le conteneur d'injection de dépendances n'accepte généralement qu'une fonction anonyme, pas un objet instancié. La fonction anonyme indiquera au conteneur comment obtenir un objet, afin qu'un service puisse être utilisé en cas de besoin. ne sera instancié que lorsque

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:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer