Affichage des articles dont le libellé est Design Pattern. Afficher tous les articles
Affichage des articles dont le libellé est Design Pattern. Afficher tous les articles

mercredi 29 mars 2023

Design Pattern Composite : exemple C#

 Voila un exemple simple en C# pour illustrer le pattern composite.

Diagramme UML


Les sources

La classe Forme

abstract class Forme
{
    protected string nom;

    public Forme(string nom)
    {
        this.nom = nom;
    }

    public virtual void Ajouter(Forme f)
    {
        throw new NotImplementedException();
    }

    public virtual void Retirer(Forme f)
    {
        throw new NotImplementedException();
    }

    public virtual void Afficher(int profondeur)
    {
        Console.WriteLine(new string('-', profondeur) + nom);
    }

    public abstract double CalculerAire();
}


La classe Carre
class Carre : Forme
{
    private double cote;

    public Carre(string nom, double cote) : base(nom)
    {
        this.cote = cote;
    }

    public override double CalculerAire()
    {
        return cote * cote;
    }
}

La classe Cercle
class Cercle : Forme
{
    private double rayon;

    public Cercle(string nom, double rayon) : base(nom)
    {
        this.rayon = rayon;
    }

    public override double CalculerAire()
    {
        return Math.PI * rayon * rayon;
    }
}

La classe Composite
class Composite : Forme
{
    private List<Forme> enfants = new List<Forme>();

    public Composite(string nom) : base(nom)
    {
    }

    public override void Ajouter(Forme f)
    {
        enfants.Add(f);
    }

    public override void Retirer(Forme f)
    {
        enfants.Remove(f);
    }

    public override void Afficher(int profondeur)
    {
        Console.WriteLine(new string('-', profondeur) + "+ " + nom);

        foreach (Forme enfant in enfants)
        {
            enfant.Afficher(profondeur + 2);
        }
    }

    public override double CalculerAire()
    {
        double aire = 0;

        foreach (Forme enfant in enfants)
        {
            aire += enfant.CalculerAire();
        }

        return aire;
    }
}

 Exemple d'utilisation :

static void Main(string[] args)
{
    Composite groupe1 = new Composite("Groupe 1");
    groupe1.Ajouter(new Cercle("Cercle 1", 3));
    groupe1.Ajouter(new Carre("Carre 1", 4));
    groupe1.Ajouter(new Carre("Carre 2", 5));

    Composite groupe2 = new Composite("Groupe 2");
    groupe2.Ajouter(new Cercle("Cercle 2", 2));
    groupe2.Ajouter(new Carre("Carre 3", 3));
    groupe2.Ajouter(groupe1);

    groupe2.Afficher(0);

    Console.WriteLine("Aire totale : " + groupe2.CalculerAire());
}

 

mercredi 29 août 2012

Design Pattern Composite : exemple Java

Voila un exemple simple en Java pour illustrer le pattern composite.

Diagramme UML


Les sources

La classe Forme
import java.awt.geom.Point2D;

abstract class Forme {

   Point2D position;

   void ajouterForme(Forme forme) throws Exception {
      throw new Exception("Non impémenté");
    }
   void retirerForme(Forme forme) throws Exception {
      throw new Exception("Non impémenté");
   }

   abstract void dessiner();

   abstract float calculerVolume();
}

La classe Carre
import java.awt.geom.Point2D;

class Carre extends Forme {

int hauteur;

   int largeur;

   public Carre(Point2D position, int hauteur, int largeur) {
      this.position = position;
      this.hauteur = hauteur;
      this.largeur = largeur;
   }

   @Override
   public void dessiner() {
      ...
   }

   @Override
   public float calculerVolume() {
      return hauteur * largeur;
   }
}

La classe Cercle
class Cercle extends Forme {

   int rayon;

   public Cercle(int rayon) {
      this.rayon = rayon;
   }

   @Override
   public void dessiner() {
      ...
   }
   @Override
   public float calculerVolume() {
      return (float)Math.PI * rayon * rayon;
   }
}

La classe Groupe
import java.util.HashSet;
import java.util.Set;

class Groupe extends Forme {

   private Set<forme> formes;

   public Groupe() {
      this.formes = new HashSet<forme>();
   }

   @Override
   public void ajouterForme(Forme forme) {
      formes.add(forme);
   }

   @Override
   public void retirerForme(Forme forme) {
      formes.remove(forme);
   }

   @Override
   public void dessiner() {
      for (Forme forme : formes) {
         forme.dessiner();
      }
   }
   @Override
   public float calculerVolume() {
      float volume = 0;
      for (Forme forme : formes) {
         volume += forme.calculerVolume();
      }
      return volume;
   }
}

mercredi 21 avril 2010

Design Pattern Composite


Le pattern Composite est constitué d’objets ayant le même comportement sur une profondeur variable. Cela permet d’interagir sans avoir à connaître si on parle à un objet métier ou à un groupe.

Description du problème

Lorsque l’on travaille avec des données sous forme d’arbre, il est souvent nécessaire de différencier les branches des feuilles pour savoir quel traitement effectuer.

Pour illustrer le contexte, prenons un exemple :
Nous souhaitons faire une application de dessin qui manipule des objets « graphiques » de base (carré, cercle, triangle,...). L’utilisateur lui a besoin de formes plus complexes qui seront fait à partir de formes de base ou même d’assemblage d’autres formes complexes. Il est donc nécessaire que ces formes complexes se comportent de la même façon qu’une forme simple.

Si on utilise un arbre simple, la programmation devient compliquée car il faut parcourir entièrement cet arbre tout en différenciant les actions réalisées sur les branches et les actions réalisées sur les feuilles. Cela nécessite du code et généralement des méthodes récursives pour effectuer les opérations.

Ce pattern répond à ce type de problème.

Diagramme UML


Définition de la solution

Composant : C’est la classe abstraite pour tous les composants, y compris les Composés. Elle déclare les interfaces pour les « opérations » et définit les méthodes de manipulation des enfants.
Feuille : Représente les « feuilles » dans la composition. Elle met en œuvre toutes les méthodes « opération ».
Composé : Elle représente un composant composite (Pouvant avoir des enfants), elle implémente les méthodes pour la manipulation des enfants (ajout, suppression,…) ainsi que les méthodes « opérations »

Le pattern Composite permet au client de ne pas avoir à se soucier s’il interagi avec une feuille ou une branche (Composé).

Le composé s’occupera lui même de transmettre les demandes aux feuilles. On pourra même rajouter de l’intelligence au niveau de la branche.

Dans notre exemple, on pourrait très bien imaginer un calcul de volume : chaque feuille calcule son volume et le composé additionne tous ces volumes.

Le client exécute une « opération » sur un composé. Ce composé exécute un prétraitement (si besoin), parcoure tous ces fils en demandant l’exécution de la même opération, puis fait un post-traitement (si nécessaire).

Variante

L’élément « composant » peut être une simple interface. Mais alors il faut implémenter dans chaque feuille les méthodes pour la manipulation des fils.

Conséquences

L’arbre ainsi réalisé est fortement typé. Il ne peut donc pas être utilisé de façon générique mais facilite fortement le développement du « Client ».

L’interaction entre les branches et les feuilles en est aussi simplifié; les branches ne s’occupant que de retransmettre les ordres aux feuilles sans avoir à connaître leur comportement interne.

Ce design-paterne ne doit être utilisé que si les feuilles et les branches ont des opérations communes (déclaré dans la classe composant).

Exemple