Modèles de conception

Classification des modèles de conception

Les 23 modèles de conception classiques sont regroupés en trois catégories : créationnels, structurels et comportementaux.

Modèles créationnels

Ces modèles se concentrent sur la création d'objets de manière effficace, en séparant la logique de création de l'utilisation des objets pour optimiser les ressources systèmes.

  • Simple Factory
  • Factory Method
  • Abstract Factory
  • Builder
  • Prototype
  • Singleton

Remarque : Le modèle Simple Factory n'est pas officiellement inclus dans les 23 modèles du GoF.

Modèles structurels

Ces modèles traitent de la composition des objets et de leurs relations, influençant la maintenabilité, la robustesse et le couplage du code.

  • Facade
  • Adapter
  • Proxy
  • Decorator
  • Bridge
  • Composite
  • Flyweight

Modèles comportementaux

Ces modèles se concentrent sur les interactions et le comportement des objets pour améliorer leur collaboration et la clarté des opérations.

  • Template Method
  • Observer
  • State
  • Strategy
  • Chain of Responsibility
  • Command
  • Visitor
  • Mediator
  • Memento
  • Iterator
  • Interpreter

Principes fondamentaux des modèles de conception

Principe Ouvert/Fermé (Open Close Principle)

Les entités logicielles doivent être ouvertes à l'extension mais fermées à la modification, permettant ainsi des extensions sans altérer le code existant pour une meilleure maintenabilité.

Principe de Substitution de Liskov (Liskov Substitution Principle)

Les objets d'une classe dérivée doivent pouvoir remplacer ceux de la classe de base sans affecter la fonctionnalité, garantissant ainsi une réutilisation fiable via l'héritage.

Principe d'Inversion de Dépendance (Dependence Inversion Principle)

Les modules de haut niveau ne doivent pas dépendre des modules de bas niveau ; les deux doivent dépendre d'abstractions pour une conception flexible.

Principe de Ségrégation des Interfaces (Interface Segregation Principle)

Utiliser plusieurs interfaces spécifiques est préférable à une interface générale pour réduire le couplage entre les classes.

Loi de Demeter (Principe de Connaissance Minimale)

Un objet doit interagir avec un nombre minimal d'autres objets pour maintenir une indépendance modulaire dans le système.

Principe de Réutilisation par Composition (Composite Reuse Principle)

Privilégier la composition ou l'agrégation plutôt que l'héritage pour favoriser une réutilisation flexible des composants.

Implémentations de modèles créationnels courants

Modèle Factory

Ce modèle encapsule la logique de création d'objets, exposant une interface commmune pour instancier des objets sans révéler les détails au client.

class Forme:
    def dessiner(self):
        raise NotImplementedError

class Cercle(Forme):
    def dessiner(self):
        print('dessiner un cercle')

class Rectangle(Forme):
    def dessiner(self):
        print('dessiner un rectangle')

class UsineFormes:
    def creer(self, type_forme):
        if type_forme == 'Cercle':
            return Cercle()
        elif type_forme == 'Rectangle':
            return Rectangle()
        return None

usine = UsineFormes()
instance = usine.creer('Cercle')
instance.dessiner()

Modèle Singleton

Ce modèle garantit qu'une classe n'a qu'une seule instance et fournit un point d'accès global à celle-ci.

class Singleton:
    _instance = None

    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance

class MaClasse(Singleton):
    def __init__(self, nom):
        self.nom = nom

objet1 = MaClasse("Alice")
objet2 = MaClasse("Bob")
print(objet1.nom)
print(objet2.nom)

Modèle Builder

Ce modèle sépare la construction d'un objet complexe de sa représentation, permettant de créer différentes représentatinos avec le même processus de construction.

class ConstructeurPersonne:
    def construire_tete(self):
        pass

    def construire_corps(self):
        pass

    def construire_bras(self):
        pass

    def construire_jambes(self):
        pass

class ConstructeurMince(ConstructeurPersonne):
    type_personne = 'mince'
    def construire_tete(self):
        print(f"Construction de la tête {self.type_personne}")

    def construire_corps(self):
        print(f"Construction du corps {self.type_personne}")

    def construire_bras(self):
        print(f"Construction des bras {self.type_personne}")

    def construire_jambes(self):
        print(f"Construction des jambes {self.type_personne}")

class ConstructeurGros(ConstructeurPersonne):
    type_personne = 'gros'
    def construire_tete(self):
        print(f"Construction de la tête {self.type_personne}")

    def construire_corps(self):
        print(f"Construction du corps {self.type_personne}")

    def construire_bras(self):
        print(f"Construction des bras {self.type_personne}")

    def construire_jambes(self):
        print(f"Construction des jambes {self.type_personne}")

class Directeur:
    def __init__(self, constructeur):
        self.constructeur = constructeur

    def creer_personne(self):
        self.constructeur.construire_tete()
        self.constructeur.construire_corps()
        self.constructeur.construire_bras()
        self.constructeur.construire_jambes()

# Exemple d'utilisation
constructeur_mince = ConstructeurMince()
directeur = Directeur(constructeur_mince)
directeur.creer_personne()

constructeur_gros = ConstructeurGros()
directeur.constructeur = constructeur_gros
directeur.creer_personne()

Implémentations de modèles comportementaux courants

Modèle Template Method

Ce modèle définit le squelette d'un algorithme dans une méthode, déléguant certaines étapes à des sous-classes pour personnalisation sans changer la structure globale.

class Inscription:
    def s_inscrire(self):
        pass

    def se_connecter(self):
        pass

    def authentifier(self):
        self.s_inscrire()
        self.se_connecter()

class InscriptionParQQ(Inscription):
    def s_inscrire(self):
        print("--- Inscription via QQ ---")

    def se_connecter(self):
        print('--- Connexion via QQ ---')

class InscriptionParWeChat(Inscription):
    def s_inscrire(self):
        print("--- Inscription via WeChat ---")

    def se_connecter(self):
        print('--- Connexion via WeChat ---')

if __name__ == "__main__":
    inscription_qq = InscriptionParQQ()
    inscription_qq.authentifier()

    inscription_wechat = InscriptionParWeChat()
    inscription_wechat.authentifier()

Modèle Observer

Ce modèle établit une relation de dépendance un-à-plusieurs entre objets, où un changement d'état dans un objet notifie automatiquement tous ses observateurs dépendants.

class ObservateurBase:
    def __init__(self):
        self._sujets_observés = []

    def attacher(self, sujet):
        if sujet not in self._sujets_observés:
            self._sujets_observés.append(sujet)
            print(f"[{self.nom}] a ajouté [{sujet}] à la liste d'observation")

    def détacher(self, sujet):
        try:
            self._sujets_observés.remove(sujet)
            print(f"Arrêt d'observation de [{sujet}]")
        except ValueError:
            pass

    def notifier(self):
        for sujet in self._sujets_observés:
            sujet.mettre_à_jour(self)

class Observateur(ObservateurBase):
    def __init__(self, nom):
        super().__init__()
        self.nom = nom
        self._message = ''

    @property
    def message(self):
        return self._message

    @message.setter
    def message(self, contenu):
        self._message = contenu
        self.notifier()

class SujetAlpha:
    def mettre_à_jour(self, observateur):
        print(f"Alpha: Message reçu de [{observateur.nom}]: [{observateur.message}]")

class SujetBeta:
    def mettre_à_jour(self, observateur):
        print(f"Beta: Message reçu de [{observateur.nom}]: [{observateur.message}]")

if __name__ == "__main__":
    observateur1 = Observateur("Sentinelle A")
    observateur2 = Observateur("Sentinelle B")

    sujet_alpha = SujetAlpha()
    sujet_beta = SujetBeta()

    observateur1.attacher(sujet_alpha)
    observateur1.attacher(sujet_beta)

    observateur2.attacher(sujet_beta)

    observateur1.message = "Alerte: Approche ennemie détectée"
    observateur2.message = "Notification: Retraite urgente requise"

Étiquettes: design-patterns Python factory-pattern singleton-pattern builder-pattern

Publié le 2 juin à 05h49