Introduction aux modèles de performance d'objets
La programmation orientée objet résout efficacement les problèmes d'abstraction, mais cela implique des coûts en termes de ressources. Dans la plupart des cas, ces coûts sont négligeables. Cependant, pour des scénarios spécifiques, il est crucial de les gérer avec soin pour optimiser les performances.
Cet article explore deux modèles de conception qui ciblent l'optimisation des performances des objets : Singleton et Flyweight.
Modèle Singleton
Problématique
Dans certains systèmes logiciels, il est nécessaire de garantir qu'une classe ne possède qu'une seule instance pour maintenir la cohérence et l'efficacité. Comment concevoir une classe pour restreindre l'instanciation à un unique objet ?
Définition
Le modèle Singleton assure qu'une classe a une seule instance tout en fournissant un point d'accès global. — Tiré de "Design Patterns" du GoF.
Implémentation
Voici un exemple en C++ utilisant un verrouillage pour la sécurité dans les environnements multithreads :
#include <iostream>
#include <mutex>
class SingletonExemple {
private:
static SingletonExemple* instanceUnique;
static std::mutex verrou;
SingletonExemple() {}
public:
static SingletonExemple* obtenirInstance() {
if (instanceUnique == nullptr) {
std::lock_guard<std::mutex> gardien(verrou);
if (instanceUnique == nullptr) {
instanceUnique = new SingletonExemple();
}
}
return instanceUnique;
}
void afficherMessage() {
std::cout << "Instance Singleton active." << std::endl;
}
};
SingletonExemple* SingletonExemple::instanceUnique = nullptr;
std::mutex SingletonExemple::verrou;
int main() {
SingletonExemple* ptr1 = SingletonExemple::obtenirInstance();
ptr1->afficherMessage();
SingletonExemple* ptr2 = SingletonExemple::obtenirInstance();
ptr2->afficherMessage();
return 0;
}
Points clés
- Le constructeur de l'instance Singleton peut être défini comme protected pour permettre l'héritage.
- Il est recommandé de désactiver les opérations de copie et de clonage pour préserver l'unicité de l'instance.
- Pour la sécurité multithread, la double vérification du verrou doit être correctement implémentée.
Modèle Flyweight
Problématique
L'utilisation d'objets de granularité fine peut conduire à une consommation excessive de mémoire. Comment réduire ce coût tout en maintenant une interface orientée objet pour les clients ?
Définition
Le modèle Flyweight applique le partage d'objets pour supporter efficacement un grand nombre d'objets de granularité fine. — Tiré de "Design Patterns" du GoF.
Implémentation
L'exemple suivant illustre un système de partage d'objets pour des sites web, avec une modification de la structure et des noms :
#include <iostream>
#include <string>
#include <map>
class Utilisateur {
public:
std::string nomUtilisateur;
Utilisateur(const std::string& nom) : nomUtilisateur(nom) {}
};
class SiteWeb {
public:
virtual void traiterRequete(Utilisateur* utilisateur) = 0;
};
class SiteConcret : public SiteWeb {
public:
void traiterRequete(Utilisateur* utilisateur) override {
std::cout << "Traitement pour : " << utilisateur->nomUtilisateur << std::endl;
}
};
class FabriqueSites {
private:
std::map<std::string, SiteWeb*> poolSites;
public:
SiteWeb* obtenirSite(const std::string& categorie) {
auto it = poolSites.find(categorie);
if (it != poolSites.end()) {
return it->second;
} else {
SiteWeb* nouveauSite = new SiteConcret();
poolSites[categorie] = nouveauSite;
return nouveauSite;
}
}
};
int main() {
FabriqueSites fabrique;
Utilisateur* utilisateur1 = new Utilisateur("Alice");
Utilisateur* utilisateur2 = new Utilisateur("Bob");
SiteWeb* siteA = fabrique.obtenirSite("video");
siteA->traiterRequete(utilisateur1);
SiteWeb* siteB = fabrique.obtenirSite("video");
siteB->traiterRequete(utilisateur2);
delete utilisateur1;
delete utilisateur2;
return 0;
}
Points clés
- Flyweight réduit le nombre d'objets en partageant des états immuables, optimisant ainsi l'utilisation de la mémoire.
- Il est essentiel de distinguer les états intrinsèques (partagés) et extrinsèques (propres à l'objet).
- L'évaluation du seuil d'objets nécessitant le partage doit être basée sur les besoins spécifiques de l'application.