Maison développement back-end tutoriel php Chargement paresseux et références circulaires

Chargement paresseux et références circulaires

Dec 22, 2024 am 01:58 AM

Lazy Loading and Circular References

Table des matières

  1. Chargement paresseux
  2. Implémentation de base du chargement différé
  3. Modèle de proxy pour le chargement paresseux
  4. Gestion des références circulaires
  5. Techniques de mise en œuvre avancées
  6. Meilleures pratiques et pièges courants

Chargement paresseux

Qu’est-ce que le chargement différé ?

Le chargement différé est un modèle de conception qui diffère l'initialisation des objets jusqu'à ce qu'ils soient réellement nécessaires. Au lieu de charger tous les objets au démarrage de l'application, les objets sont chargés à la demande, ce qui peut améliorer considérablement les performances et l'utilisation de la mémoire.

Avantages clés

  1. Efficacité de la mémoire : seuls les objets nécessaires sont chargés en mémoire
  2. Chargement initial plus rapide : l'application démarre plus rapidement car tout n'est pas chargé en même temps
  3. Optimisation des ressources : les connexions à la base de données et les opérations sur les fichiers sont effectuées uniquement en cas de besoin
  4. Meilleure évolutivité : une empreinte mémoire réduite permet une meilleure mise à l'échelle des applications

Implémentation de base du chargement différé

Commençons par un exemple simple pour comprendre le concept de base :

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

class User {

    private ?Profile $profile = null;

    private int $id;

 

    public function __construct(int $id) {

        $this->id = $id;

        // Notice that Profile is not loaded here

        echo "User {$id} constructed without loading profile\n";

    }

 

    public function getProfile(): Profile {

        // Load profile only when requested

        if ($this->profile === null) {

            echo "Loading profile for user {$this->id}\n";

            $this->profile = new Profile($this->id);

        }

        return $this->profile;

    }

}

 

class Profile {

    private int $userId;

    private array $data;

 

    public function __construct(int $userId) {

        $this->userId = $userId;

        // Simulate database load

        $this->data = $this->loadProfileData($userId);

    }

 

    private function loadProfileData(int $userId): array {

        // Simulate expensive database operation

        sleep(1); // Represents database query time

        return ['name' => 'John Doe', 'email' => 'john@example.com'];

    }

}

Copier après la connexion
Copier après la connexion

Comment fonctionne cette implémentation de base

  1. Lorsqu'un objet Utilisateur est créé, seul l'ID utilisateur est stocké
  2. L'objet Profile n'est pas créé tant que getProfile() n'est pas appelé
  3. Une fois chargé, le profil est mis en cache dans la propriété $profile
  4. Les appels ultérieurs à getProfile() renvoient l'instance mise en cache

Modèle de proxy pour le chargement paresseux

Le modèle Proxy offre une approche plus sophistiquée du chargement paresseux :

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

interface UserInterface {

    public function getName(): string;

    public function getEmail(): string;

}

 

class RealUser implements UserInterface {

    private string $name;

    private string $email;

    private array $expensiveData;

 

    public function __construct(string $name, string $email) {

        $this->name = $name;

        $this->email = $email;

        $this->loadExpensiveData(); // Simulate heavy operation

        echo "Heavy data loaded for {$name}\n";

    }

 

    private function loadExpensiveData(): void {

        sleep(1); // Simulate expensive operation

        $this->expensiveData = ['some' => 'data'];

    }

 

    public function getName(): string {

        return $this->name;

    }

 

    public function getEmail(): string {

        return $this->email;

    }

}

 

class LazyUserProxy implements UserInterface {

    private ?RealUser $realUser = null;

    private string $name;

    private string $email;

 

    public function __construct(string $name, string $email) {

        // Store only the minimal data needed

        $this->name = $name;

        $this->email = $email;

        echo "Proxy created for {$name} (lightweight)\n";

    }

 

    private function initializeRealUser(): void {

        if ($this->realUser === null) {

            echo "Initializing real user object...\n";

            $this->realUser = new RealUser($this->name, $this->email);

        }

    }

 

    public function getName(): string {

        // For simple properties, we can return directly without loading the real user

        return $this->name;

    }

 

    public function getEmail(): string {

        // For simple properties, we can return directly without loading the real user

        return $this->email;

    }

}

Copier après la connexion
Copier après la connexion

L'implémentation du modèle de proxy

  1. L'interface utilisateur garantit que les objets réels et proxy ont la même interface
  2. RealUser contient l'implémentation lourde réelle
  3. LazyUserProxy agit comme un substitut léger
  4. Le proxy ne crée l'objet réel que lorsque cela est nécessaire
  5. Des propriétés simples peuvent être renvoyées directement depuis le proxy

Gestion des références circulaires

Les références circulaires présentent un défi particulier. Voici une solution complète :

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

class User {

    private ?Profile $profile = null;

    private int $id;

 

    public function __construct(int $id) {

        $this->id = $id;

        // Notice that Profile is not loaded here

        echo "User {$id} constructed without loading profile\n";

    }

 

    public function getProfile(): Profile {

        // Load profile only when requested

        if ($this->profile === null) {

            echo "Loading profile for user {$this->id}\n";

            $this->profile = new Profile($this->id);

        }

        return $this->profile;

    }

}

 

class Profile {

    private int $userId;

    private array $data;

 

    public function __construct(int $userId) {

        $this->userId = $userId;

        // Simulate database load

        $this->data = $this->loadProfileData($userId);

    }

 

    private function loadProfileData(int $userId): array {

        // Simulate expensive database operation

        sleep(1); // Represents database query time

        return ['name' => 'John Doe', 'email' => 'john@example.com'];

    }

}

Copier après la connexion
Copier après la connexion

Comment fonctionne la gestion des références circulaires

  1. Le LazyLoader maintient un registre d'instances et d'initialiseurs
  2. Une pile d'initialisation suit la chaîne de création d'objet
  3. Les références circulaires sont détectées à l'aide de la pile
  4. Les objets sont créés avant d'être initialisés
  5. L'initialisation se produit une fois que tous les objets requis existent
  6. La pile est toujours nettoyée, même si des erreurs surviennent

Techniques de mise en œuvre avancées

Utilisation d'attributs pour le chargement paresseux (PHP 8)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

interface UserInterface {

    public function getName(): string;

    public function getEmail(): string;

}

 

class RealUser implements UserInterface {

    private string $name;

    private string $email;

    private array $expensiveData;

 

    public function __construct(string $name, string $email) {

        $this->name = $name;

        $this->email = $email;

        $this->loadExpensiveData(); // Simulate heavy operation

        echo "Heavy data loaded for {$name}\n";

    }

 

    private function loadExpensiveData(): void {

        sleep(1); // Simulate expensive operation

        $this->expensiveData = ['some' => 'data'];

    }

 

    public function getName(): string {

        return $this->name;

    }

 

    public function getEmail(): string {

        return $this->email;

    }

}

 

class LazyUserProxy implements UserInterface {

    private ?RealUser $realUser = null;

    private string $name;

    private string $email;

 

    public function __construct(string $name, string $email) {

        // Store only the minimal data needed

        $this->name = $name;

        $this->email = $email;

        echo "Proxy created for {$name} (lightweight)\n";

    }

 

    private function initializeRealUser(): void {

        if ($this->realUser === null) {

            echo "Initializing real user object...\n";

            $this->realUser = new RealUser($this->name, $this->email);

        }

    }

 

    public function getName(): string {

        // For simple properties, we can return directly without loading the real user

        return $this->name;

    }

 

    public function getEmail(): string {

        // For simple properties, we can return directly without loading the real user

        return $this->email;

    }

}

Copier après la connexion
Copier après la connexion

Meilleures pratiques et pièges courants

Meilleures pratiques

  1. Effacer les points d'initialisation : indiquez toujours clairement où se produit le chargement paresseux
  2. Gestion des erreurs : implémentez une gestion robuste des erreurs pour les échecs d'initialisation
  3. Documentation : Documentez les propriétés chargées paresseusement et leurs exigences d'initialisation
  4. Tests : testez les scénarios de chargement paresseux et impatients
  5. Surveillance des performances : surveillez l'impact du chargement paresseux sur votre application

Pièges courants

  1. Fuites de mémoire : Ne pas publier de références à des objets chargés paresseux inutilisés
  2. Dépendances circulaires : Ne gère pas correctement les références circulaires
  3. Chargement paresseux inutile : appliquer un chargement paresseux là où il n'est pas bénéfique
  4. Thread Safety : ne prend pas en compte les problèmes d'accès simultané
  5. État incohérent : ne gère pas correctement les échecs d'initialisation

Considérations relatives aux performances

Quand utiliser le chargement paresseux

  • Objets volumineux qui ne sont pas toujours nécessaires
  • Objets dont la création nécessite des opérations coûteuses
  • Objets qui pourraient ne pas être utilisés dans chaque demande
  • Collections d'objets dont seul un sous-ensemble est généralement utilisé

Quand ne pas utiliser le chargement paresseux

  • Objets petits et légers
  • Des objets presque toujours nécessaires
  • Objets dont le coût d'initialisation est minime
  • Cas où la complexité du chargement paresseux l'emporte sur les avantages

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 de ce site Web
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

Article chaud

Repo: Comment relancer ses coéquipiers
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Combien de temps faut-il pour battre Split Fiction?
3 Il y a quelques semaines By DDD
R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
1 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: Comment obtenir des graines géantes
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌

Article chaud

Repo: Comment relancer ses coéquipiers
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Combien de temps faut-il pour battre Split Fiction?
3 Il y a quelques semaines By DDD
R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
1 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: Comment obtenir des graines géantes
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌

Tags d'article chaud

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

11 meilleurs scripts de raccourcissement d'URL PHP (gratuit et premium) 11 meilleurs scripts de raccourcissement d'URL PHP (gratuit et premium) Mar 03, 2025 am 10:49 AM

11 meilleurs scripts de raccourcissement d'URL PHP (gratuit et premium)

Introduction à l'API Instagram Introduction à l'API Instagram Mar 02, 2025 am 09:32 AM

Introduction à l'API Instagram

Travailler avec les données de session Flash dans Laravel Travailler avec les données de session Flash dans Laravel Mar 12, 2025 pm 05:08 PM

Travailler avec les données de session Flash dans Laravel

Construisez une application React avec un Laravel Back End: Partie 2, React Construisez une application React avec un Laravel Back End: Partie 2, React Mar 04, 2025 am 09:33 AM

Construisez une application React avec un Laravel Back End: Partie 2, React

Misque de réponse HTTP simplifié dans les tests Laravel Misque de réponse HTTP simplifié dans les tests Laravel Mar 12, 2025 pm 05:09 PM

Misque de réponse HTTP simplifié dans les tests Laravel

Curl dans PHP: Comment utiliser l'extension PHP Curl dans les API REST Curl dans PHP: Comment utiliser l'extension PHP Curl dans les API REST Mar 14, 2025 am 11:42 AM

Curl dans PHP: Comment utiliser l'extension PHP Curl dans les API REST

12 meilleurs scripts de chat PHP sur Codecanyon 12 meilleurs scripts de chat PHP sur Codecanyon Mar 13, 2025 pm 12:08 PM

12 meilleurs scripts de chat PHP sur Codecanyon

Notifications à Laravel Notifications à Laravel Mar 04, 2025 am 09:22 AM

Notifications à Laravel

See all articles