Vous pourrez peut-être trouver cette définition du pattern composite :
Citation : SomeoneLe pattern Composite compose des objets en arborescences.
Ceci permet de représenter une ou plusieurs hiérarchies d'objets sans se soucier de savoir si un objet est composé ou non d'autres objets.
Pour faire court, ce pattern permet de gérer très facilement des données en les structurant en hiérarchie. Voyez ça comme un
JTree :
En fait, vous pouvez avoir un objet composé d'un ou plusieurs éléments qui peuvent, eux aussi, être composés d'autres éléments, etc.
Afin de simplifier la chose, imaginez une voiture. Cette dernière est composée d'un habitacle, d'un moteur, d'un bas de caisse.
Mais ces éléments sont, eux aussi, composés d'autre composants. Ainsi, nous pouvons voir que :
- le moteur est composé d'un radiateur, d'injecteurs, d'un bloc moteur. Mais le bloc moteur est lui aussi composé de telles pièces et de telles autres...
- le radiateur est composé de telles et telles pièces aussi...
- les injecteurs sont des pièces... Ils ne sont pas composés !
On peut aller très loin dans ce type de hiérarchie...
Vous voyez mieux, j'espère !
Si nous en revenons à notre forum, nous pouvez voir que la structure en grappe convient très bien. Il n'y aura pas de branches mixtes, par là entendez : des branches ayant à la fois des messages et des salons (par exemple).
Avant de vous fournir un exemple de code source, voici le diagramme de classe que j'ai fait pour vous :
On le trouve bizarre, ton diagramme !
Je sais, les diagrammes de classes peuvent sembler indigestes...

Par contre, vu que vous commencez à savoir les lire, vous devriez voir que :
- vous avez une super-classe dont dérivent toutes les autres et dans laquelle la méthode toString()
est définie ;
- une classe Message qui hérite directement de cette super-classe ;
- une autre classe abstraite (eh oui, la première super-classe est aussi abstraite), qui hérite de la super-classe, dans laquelle les méthodes add()
, remove()
et getChilds()
sont définies ;
- et enfin les sous-classes concrètes héritant de la classe mentionnée plus haut !
La sous-classe
ComposantForum a une variable d'instance
tab qui va contenir les composants de chaque objet !
La méthode
toString()
est redéfinie au premier niveau d'héritage.
Voici le diagramme de classe que j'ai réellement utilisé, ceci dû à certaines restrictions sur certains types d'objets :
Pourquoi avoir créé les classes Theme et Salon ?
Tout simplement car les objets de ces deux types auront des restrictions concernant le genre d'objets dont ils sont constitués...
C'est dans ces classes que nous allons pouvoir gérer les composants de nos objets ! Ainsi, nous pourrons seulement ajouter des topics dans un salon, des salons dans un thème, des thèmes dans un forum...
Vous comprenez mieux, j'espère !
Voici les codes source des classes que j'ai créées (j'ai essayé de les regrouper du haut de la hiérarchie vers le bas).
Classe Composant.java
Code : Java1
2
3
4
5
6
7 | package com.sdz.composite;
public abstract class Composant {
//Cette variable sert seulement pour mon exemple
protected String tabulation = "";
public abstract String toString();
}
|
Classe Message.java
Code : Java 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | package com.sdz.composite;
public class Message extends Composant{
private String message;
public Message(String message){
this.message = (message.trim().equals("") || message == null) ? "" : message;
this.tabulation = "\t\t";
}
public String toString() {
return this.tabulation + this.message;
}
}
|
Classe ComposantForum.java
Code : Java 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 | package com.sdz.composite;
import java.util.ArrayList;
abstract class ComposantForum extends Composant{
protected ArrayList tab = new ArrayList();
protected String name = "";
public ComposantForum(){}
public ComposantForum(String nom){this.name = nom;}
public void add(Composant comp){
this.tab.add(comp);
}
public void remove(int i){
this.tab.remove(i);
}
public ArrayList getChilds(){
return this.tab;
}
public String toString(){
String str = "";
str += this.tabulation +"+ " + name + "\n";
for(Object comp : this.tab){
str += this.tabulation + ((Composant)comp).toString() + "\n";
}
return str;
}
}
|
Classes Forum.java et Topic.java
Code : Java 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | package com.sdz.composite;
import java.util.ArrayList;
public class Forum extends ComposantForum{
public Forum(){
this.name = "Forum";
}
public Forum(String nom) {
super(nom);
}
public void add(Composant comp){
if((comp instanceof Theme))
this.tab.add(comp);
}
}
|
Code : Java 1
2
3
4
5
6
7
8
9
10
11
12
13
14 | package com.sdz.composite;
public class Topic extends ComposantForum {
public Topic(String string) {
super(string);
this.tabulation += "\t\t";
}
public void add(Composant comp){
if((comp instanceof Message))
this.tab.add(comp);
}
}
|
Classe Salon.java et Theme.java
Code : Java 1
2
3
4
5
6
7
8
9
10
11
12
13
14 | package com.sdz.composite;
public class Salon extends ComposantForum{
public Salon(String nom) {
super(nom);
this.tabulation += "\t";
}
public void add(Composant comp){
if((comp instanceof Topic))
this.tab.add(comp);
}
}
|
Code : Java 1
2
3
4
5
6
7
8
9
10
11
12
13
14 | package com.sdz.composite;
public class Theme extends ComposantForum{
public Theme(String nom) {
super(nom);
this.tabulation += "\t";
}
public void add(Composant comp){
if((comp instanceof Salon))
this.tab.add(comp);
}
}
|
Classes Programmation.java et SiteWeb.java
Code : Java1
2
3
4
5
6
7
8 | package com.sdz.composite;
public class Programmation extends Theme{
public Programmation(String nom) {
super(nom);
}
}
|
Code : Java1
2
3
4
5
6
7
8 | package com.sdz.composite;
public class SiteWeb extends Theme {
public SiteWeb(String nom) {
super(nom);
}
}
|
Classes CPlus.java, Java.java, Html.java, PHP.java...
Code : Java1
2
3
4
5
6
7
8
9 | package com.sdz.composite;
public class Cplus extends Salon{
public Cplus(String nom) {
super(nom);
}
}
|
Code : Java1
2
3
4
5
6
7
8 | package com.sdz.composite;
public class Html extends Salon {
public Html(String nom) {
super(nom);
}
}
|
Code : Java1
2
3
4
5
6
7 | package com.sdz.composite;
public class Java extends Salon {
public Java(String nom) {
super(nom);;
}
}
|
Code : Java1
2
3
4
5
6
7
8 | package com.sdz.composite;
public class Php extends Salon {
public Php(String nom) {
super(nom);
}
}
|
Code : Java1
2
3
4
5
6
7
8 | package com.sdz.composite;
public class C extends Salon {
public C(String nom) {
super(nom);
}
}
|
Pfiou !... Il y en a, des classes...
Même si vous aviez bien compris comment les objets allaient se comporter entre eux, vous devez mieux comprendre avec du code sous les yeux !

Maintenant, vous comprenez comment on gère l'interdiction de certains composants dans d'autres...
Dans notre cas, nous n'avons rien fait de spécial !
Mais rien ne vous empêche de faire une levée d'exception si l'utilisateur essaie d'ajouter un type d'objet prohibé !
Vu que nous avons toutes nos classes, il est grand-temps de voir comment celles-ci se comportent...
Voici un code qui permet de tester notre hiérarchie :
Code : Java 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 | //J'ai déclaré mes classes dans un autre package, d'où l'import
import com.sdz.composite.*;
public class Test {
public static void main(String[] args) {
//Création de l'objet Forum
Forum fofo = new Forum();
//Création d'un thème
Theme prog = new Programmation("Thème -> Programmation <-");
//Ajoute du thème dans le forum
fofo.add(prog);
//Création d'un Salon
Salon java = new Java("Salon : Java");
//ce salon ne s'ajoutera pas : C'EST INTERDIT
fofo.add(java);
//Le salon n'aura pas non plus le thème dans la collection
java.add(prog);
//Par contre le thème aura le salon, et vu que le forum à le thème...
prog.add(java);
//On crée deux topic
Topic topic = new Topic("Je vous passe le bonjour !");
Topic topic2 = new Topic("Problème de pattern !");
//On les ajoute dans le salon
java.add(topic);
java.add(topic2);
//On ajoute les message dans les topics
topic.add(new Message("Coucou de cysboy !"));
topic.add(new Message("Coucou du SDZ ! ! !"));
topic.add(new Message("Vous suivez toujours..."));
topic2.add(new Message("Je ne comprends pas bien le pattern composite !"));
topic2.add(new Message("Même avec cet exemple tu ne comprends pas ?"));
topic2.add(new Message("C'est vrai que là... On comprend beaucoup mieux"));
//On crée un deuxième salon
Salon c = new Cplus("Salon : C++");
//On l'ajoute dans programmation
prog.add(c);
//On crée aussi un topic et on l'ajoute dans le salon
Topic topic3 = new Topic("Problème de pointeur...");
c.add(topic3);
//On lui ajoute des messages
topic3.add(new Message("Je pige rien aux pointeurs... HELP !"));
topic3.add(new Message("Va faire un tour sur le tuto de M@teo..."));
topic3.add(new Message("Ah oui !.. :p"));
//Le forum a donc :
// - un thème
// - deux salons
// * Java : 2 topics
// * C++ : 1 topic
System.out.println(fofo.toString());
}
}
|
Voilà ce que me donne ce code :
Simple,
isn't it ?
Vous avez une belle hiérarchie d'objets qui s'entremêlent : un objet
Forum, auquel vous ajoutez des thèmes ; à ces thèmes, vous ajoutez des salons qui, eux, ont des topics composés de messages.
Et lorsque vous demandez au forum de s'afficher, tout est automatique ! Même si vous passez des objets non autorisés, cela n'empêche pas le code de fonctionner !
Afin de mieux comprendre ce pattern, voici à quoi il ressemble dans Java.