Accueil
Rechercher:
sur developpez.com sur les forums
Forums | Tutoriels | F.A.Q's | Participez | Hébergement | Contacts
Club Emploi Blogs   TV   Dév. Web PHP XML Python Autres 2D-3D-Jeux Sécurité Windows Linux PC Mac
Accueil Conception Java DotNET Visual Basic  C  C++ Delphi MS-Office SQL & SGBD Oracle  4D  Business Intelligence
FORUMS JAVA FAQs TUTORIELS JAVASEARCH SOURCES LIVRES OUTILS, EDI & API ECLIPSE NETBEANS BLOG DISCUSSIONS TV
Trucs et astuces
Validité des paramètres
Documenter votre code
Assertions
Tests unitaires
Design patterns - GOF
Adaptateur
Composite
Décorateur
etat
Façade
Kit
Monteur
Pont
Proxy
Singleton
Design patterns - Avalon
IOC - Inversion Of Control
SOC - Seperation Of Concerns
COP - Component Orientated Programming
SOP - Service Orientated Programming
Autres articles
Cahier
XML Sax en java
Fractal
AspectJ

Voir aussi
Patterns du GRASP
héritage avec des EJB Entiy CMP

Ressouces java
Informations
Cours
Livres
FAQ
Outils
EDI
Ressources uml
Cours
Livres
Forums d'entraide
Géneral Java
J2EE
JBuilder
Outils EDI
Méthodes/UML/Mérise


Le composite
30 Avril 2003
Version 1.0
Par Sébastien MERIC
Remerciements : Stefan Bertholon
Composite - Design patterns - UML - Sébastien MERIC

Synopsis

Modèle de structure arborescente d'un ensemble de composants cohérents. Permet à la classe cliente de composer, et utiliser d'une manière cohérente (unique) une hiérarchie complexe d'objets.

Exploration

Imaginons que nous ayons à gérer un petit magasin, lequel offre à ses clients la possiblité d'acheter des pièces détachées, des ensembles préassemblés ou même des ensembles plus complets fait de plusieurs ensembles préassemblés. Par exemple, nous vendons des équipements et vêtements sportifs, soit en pièces détachées (chaussures, pantalon de survêtement, poids d'haltères, ...), soit en ensemble (le survêtement complet, l'haltère avec un jeu de 5 paires de poids, ...), soit enfin des packages complets (haltère + survêtement + serviette). Pour chaque article, qu'il soit composé ou en pièces détachées, nous connaissons son prix, un nom descriptif et un code barre.

Le décor étant planté, voyons comment nous pouvons nous organiser. Tout d'abord, quelques détails fonctionnels.

  • Le prix d'un ensemble est calculé suivant la méthode suivante : c'est la somme des prix de ses parties (composées ou non) moins 10%
  • Le code barre est spécifique à chaque produit vendu qu'il soit composé ou non
  • Le nom descriptif d'un ensemble contient à la fois un descriptif de l'ensemble et le descriptif des parties

Nous nous pencherons ici sur le back office de notre magasin, c'est-à-dire sur l'aide à la composition de produits pour le vendeur. Chaque produit a un ensemble de propriétés qui lui sont propres, par exemple le poids d'haltère a un poids, le rameur un encombrement, etc. ce qui explique que je leur fournisse une description (classe) à chacun.

Il n'en reste pas moins que l'interface générique servira à la composition et que nous préférons donc au niveau de ce back office, disposer d'un moyen unique de composition, et de manipulation, c'est là que le pattern intervient.

Structure

Notre stucture doit donc disposer d'un point d'entrée générique : Le produit, de feuilles pour notre arborescence : Les pièces détachées et d'objets composites.

Diagramme du composite

Implémentation

Reprenons donc notre exemple mais simplifié, je vais disposer de deux classes : barre (d'haltère) et poids et je montrerai une composition : l'haltère complète (poids + barre).

Source de l'interface Produit

/*
 * Produit.java
 *
 * Created on 12 mars 2003, 18:35
 */

package com.developpez.composite;

/**
 *
 * @author  smeric
 */
public interface Produit {

    /**
     * Fournit le prix du produit.
     * Peut être calculé.
     */
    public float getPrix();
    /**
     * Code barre unique d'un produit.
     */
    public String getCodeBarre();
    /**
     * Descriptif du produit. Peut être le résultat d'une accumulation de 
     * descriptifs si le produit est composé
     */
    public String getDescriptif();

}

Source de Barre

/*
 * halterre.java
 *
 * Created on 12 mars 2003, 18:56
 */

package com.developpez.composite;

/**
 *
 * @author  smeric
 */
public class Barre implements Produit {

    /** Creates a new instance of haltere */
    public Barre() {
    }

    /** Code barre unique d'un produit.
     */
    public String getCodeBarre() {
        return codeBarre;
    }

    /** Descriptif du produit. Peut être le résultat d'une accumulation de
     * descriptifs si le produit est composé
     */
    public String getDescriptif() {
        return descriptif;
    }

    /** Fournit le prix du produit.
     * Peut être calculé.
     */
    public float getPrix() {
        return prix;
    }

    /** Getter for property longueur.
     * @return Value of property longueur.
     */
    public float getLongueur() {
        return this.longueur;
    }

    /** Setter for property longueur.
     * @param longueur New value of property longueur.
     */
    public void setLongueur(float longueur) {
        this.longueur = longueur;
    }

    private float poids = 0;
    private float prix = 0;
    private String codeBarre;
    private String descriptif;

    /** Holds value of property longueur. */
    private float longueur;

}

Source de Poids

/*
 * Poids.java
 *
 * Created on 12 mars 2003, 18:39
 */

package com.developpez.composite;

/**
 *
 * @author  smeric
 */
public class Poids implements Produit {

    /** Creates a new instance of Poids */
    public Poids() {
    }

    public float getPoids() {
        return poids;
    }

    /** Code barre unique d'un produit.
     */
    public String getCodeBarre() {
        return codeBarre;
    }

    /** Descriptif du produit. Peut être le résultat d'une accumulation de
     * descriptifs si le produit est composé
     */
    public String getDescriptif() {
        return descriptif;
    }

    /** Fournit le prix du produit.
     * Peut être calculé.
     */
    public float getPrix() {
        return prix;
    }

    private float poids = 0;
    private float prix  = 0;
    private String codeBarre;
    private String descriptif;
}

Source de ProduitException

/*
 * ProduitException.java
 *
 * Created on 13 mars 2003, 10:59
 */

package com.developpez.composite;

import java.lang.RuntimeException;

/**
 *
 * @author  smeric
 */
public class ProduitException extends RuntimeException {
    public ProduitException() {
        super();
    }
    public ProduitException(String msg) {
        super(msg);
    }
    public ProduitException(Exception e) {
        super(e);
    }
}

Source de ProduitComposite

/*
 * ProduitComposite.java
 *
 * Created on 12 mars 2003, 19:01
 */

package com.developpez.composite;

import java.util.*;

/**
 * Classe d'implémentation d'un produit composite pour notre magasin.
 * @author  smeric
 */
public class ProduitComposite implements Produit {

    /** Creates a new instance of ProduitComposite */
    public ProduitComposite() {
        children = new ArrayList();
    }

    /** Ajoute un produit à la liste des composants
     * @param produit le produit que l'on veux ajouter au composite
     * @throws ProduitException Si le produit est null.
     */
    public void add(Produit produit) throws ProduitException {
        assert null != children;
        if (null == produit) {
            throw new ProduitException("Impossible d'ajouter un produit null");
        }
        children.add(produit);
    }

    /** Enlève un produit de la composition.
     * @param produit le produit à retirer de la composition.
     * @throws ProduitException Si le produit est null ou n'est pas dans la liste.
     */
    public void remove(Produit produit) throws ProduitException {
        assert null != children;
        if (null == produit) {
            throw new ProduitException("Impossible d'enlever un produit null");
        }

        if ( ! children.contains(produit)) {
            throw new ProduitException("Impossible d'enlever le produit, il n'est pas dans la liste");
        }

        children.remove(produit);
    }

    /** Renvoie la liste des composantes du produit sous la forme d'un itérateur.<p>
     * Voir le pattern itérateur.
     * @return La liste des composantes.
     */
    public Iterator getChildren() {
        assert null != children;
        return children.iterator();
    }

    /** Code barre unique d'un produit.
     * @return  le code barre du produit
     */
    public String getCodeBarre() {
        return codeBarre;
    }

    /** Descriptif du produit. Peut être le résultat d'une accumulation de
     * descriptifs si le produit est composé
     * @return  le descriptif composé
     */
    public String getDescriptif() {
        assert null != children;

        StringBuffer result = new StringBuffer();
        result.append(descriptif);
        result.append(" : (");

        for (Iterator i = children.iterator(); i.hasNext(); ) {
            Object objet = i.next();

            assert null != objet : "Un objet null a été trouvé dans la liste des composantes";
            assert objet instanceof Produit : "Un \"non produit\" a été trouvé dans la liste des composantes";

            Produit composant = (Produit)objet;

            result.append(composant.getDescriptif());
            if (i.hasNext()) { // on ajoute une virgule pour séparer les descriptifs
                result.append(", ");
            }
        }

        result.append(" )");
        return result.toString();
    }

    /** Fournit le prix du produit.
     * Peut être calculé.
     * @return  le prix calculé
     */
    public float getPrix() {
        float result = 0;
        for (Iterator i = children.iterator(); i.hasNext(); ) {
            Object objet = i.next();

            assert null != objet : "Un objet null a été trouvé dans la liste des composantes";
            assert objet instanceof Produit : "Un \"non produit\" a été trouvé dans la liste des composantes";

            Produit composant = (Produit)objet;

            result += composant.getPrix();
        }
        result = result * 0.9f; // soit une réducion de 10%
        return result;
    }

    private Collection children;
    private String codeBarre;
    private String descriptif;

}

Et voici un exemple d'utilisation

Barre maBarre = new Barre();
maBarre.setPrix(25f);
maBarre.setDescriptif("Barre d'haltérophilie");
maBarre.setCodeBarre("BA0001");
maBarre.setLongueur(150f);

Poids leger = new Poids();
leger.setPrix(15f);
leger.setDescriptif("Poids d'haltère");
leger.setCodeBarre("PA0001");
leger.setPoids(0.5f);

Poids moyen = new Poids();
moyen.setPrix(17f);
moyen.setDescriptif("Poids d'haltère");
moyen.setCodeBarre("PA0002");
moyen.setPoids(1f);

Poids lourd = new Poids();
lourd.setPrix(19f);
lourd.setDescriptif("Poids d'haltère");
lourd.setCodeBarre("PA0003");
lourd.setPoids(1.5f);

ProduitComposite haltere = new ProduitComposite();
haltere.add(maBarre);
haltere.add(leger);
haltere.add(moyen);
haltere.add(lourd);
Copyright (c) 2003 Sébastien MERIC. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being Le composite, and Back-Cover Texts being Ce document à été écrit pour la communauté de développeurs francophones "www.developpez.com". A copy of the license is included in the section entitled "GNU Free Documentation License".
/java/uml/composite  

Responsables bénévoles de la rubrique Java : Eric Siber et Baptiste Wicht - Contacter par EMail :
Vos questions techniques : forum d'entraide Java - Publiez vos articles, tutoriels et cours
et rejoignez-nous dans l'équipe de rédaction du club d'entraide des développeurs francophones
Nous contacter - Copyright © 2000-2008 www.developpez.com - Legal informations.