Diagramme structurel · UML 2.x
Diagramme
de Classes
Modélise la structure statique d'un système : classes, attributs, méthodes, et les relations entre elles.
Représentation d'une Classe
Une classe UML est représentée par un rectangle divisé en 3 compartiments : le nom, les attributs, et les méthodes.
Conventions de nommage
| Élément | Syntaxe & convention |
|---|---|
| Nom de classe | PascalCase, singulier, centré. Abstraites en italique. |
| Attribut | visibilité nom : Type = valeurDéfaut |
| Méthode | visibilité nom(p:Type) : TypeRetour |
| Statique | souligné — partagé par toutes les instances |
| Abstrait | italique — doit être implémenté |
Un compartiment vide peut être omis. On peut ajouter un 4ᵉ compartiment pour les contraintes ou stéréotypes.
Visibilité
Chaque attribut et méthode est précédé d'un symbole indiquant son niveau d'accès.
| Symbole | Nom | Accès | Python |
|---|---|---|---|
| + | Public | Tout le monde | attribut |
| - | Privé | Classe uniquement | __attribut |
| # | Protégé | Classe + sous-classes | _attribut |
| ~ | Package | Même package/module | convention |
Classe Abstraite & Membres Statiques
Une classe abstraite ne peut pas être instanciée directement. Son nom et ses méthodes abstraites sont en italique. Les membres statiques (partagés par toutes les instances) sont soulignés.
«abstract»)En Python : class C(ABC) pour abstrait, @abstractmethod pour méthodes abstraites. Membre statique = attribut de classe ou @classmethod.
from abc import ABC, abstractmethod
class Forme(ABC): # abstraite
nb_formes = 0 # statique
def __init__(self, couleur="noir"):
self._couleur = couleur # protégé #
Forme.nb_formes += 1
@abstractmethod
def aire(self) -> float: ... # abstraite
def getCouleur(self): # concrète
return self._couleur
@classmethod
def getNbFormes(cls): # statique
return cls.nb_formes
Interface
Une interface définit un contrat pur : uniquement des signatures de méthodes, sans implémentation. Une classe peut implémenter plusieurs interfaces.
«interface» obligatoirefrom abc import ABC, abstractmethod
class Serialisable(ABC): # «interface»
@abstractmethod
def serialiser(self) -> str: ...
@abstractmethod
def deserialiser(self, s: str): ...
class Document(Serialisable):
def serialiser(self):
return self.contenu
def deserialiser(self, s):
self.contenu = s
Réalisation multiple
Une classe peut implémenter plusieurs interfaces simultanément — c'est l'un des grands avantages des interfaces.
Stéréotypes & Annotations
Les stéréotypes précisent le rôle ou la nature d'un élément UML. Ils sont écrits entre guillemets « ».
Classe qui ne peut pas être instanciée. Peut s'exprimer par le nom en italique.
Animal
Classe purement abstraite définissant un contrat. Toutes les méthodes sont abstraites.
Comparable
Type énuméré. Liste un ensemble de valeurs constantes nommées.
Couleur
Classe utilitaire : uniquement méthodes statiques. Pas destinée à être instanciée.
MathUtils
Une seule instance possible. Constructeur privé, accès via méthode statique.
Config
Type de donnée structuré (ex: Date, Point) sans comportement complexe.
Point
Stéréotypes personnalisés
On peut créer ses propres stéréotypes pour documenter l'architecture :
«controller» — classe gérant la logique métier (MVC)«repository» — classe d'accès aux données«service» — classe de service applicatif«entity» — classe représentant une entité persistante«factory» — classe responsable de la création d'objetsVue d'ensemble des Relations
Les classes sont reliées entre elles par 5 types de relations principales, chacune avec une notation graphique précise.
Association
L'association exprime qu'une classe connaît ou utilise une autre classe. C'est le lien le plus général.
Un Étudiant est inscrit dans un Cours. L'étudiant « connaît » ses cours, mais pas nécessairement l'inverse.
class Etudiant:
def __init__(self, nom):
self.nom = nom
self.cours = [] # association
def inscrire(self, cours):
self.cours.append(cours)
Agrégation
L'agrégation est une association spéciale « tout–partie ». La partie peut exister sans le tout.
Une Équipe est composée de Joueurs. Si l'équipe se dissout, les joueurs existent toujours.
class Equipe:
def __init__(self, nom):
self.nom = nom
self.joueurs = [] # agrégation
def ajouter(self, joueur):
# joueur existe en dehors d'Equipe
self.joueurs.append(joueur)
Composition
La composition est une agrégation forte : la partie ne peut exister sans le tout. Leur cycle de vie est identique.
class Maison:
def __init__(self, adresse, nb):
self.adresse = adresse
# pièces créées DANS Maison
self.pieces = [
Piece(f"Pièce {i}")
for i in range(nb)
]
Héritage (Généralisation)
L'héritage indique qu'une classe est une spécialisation d'une autre. La flèche pointe vers le parent (la classe la plus générale).
Ne pas répliquer les attributs hérités dans l'enfant ! Un Cercle hérite de couleur depuis Forme — inutile de le réécrire.
Dépendance
La dépendance indique qu'une classe utilise temporairement une autre, sans la posséder. C'est le lien le plus faible.
Une Imprimante dépend d'un Document pour sa méthode imprimer(doc) — mais ne le stocke pas.
class Imprimante:
def imprimer(self, doc):
# 'doc' = paramètre → dépendance
# pas stocké dans self
print(doc.getContenu())
Multiplicité
La multiplicité précise le nombre d'instances qui participent à une relation, de chaque côté.
| Notation | Signification | Exemple |
|---|---|---|
| 1 | Exactement 1 | Un employé a 1 contrat |
| 0..1 | 0 ou 1 (optionnel) | Une personne a 0 ou 1 permis |
| * | 0 ou plusieurs | Un client a 0 ou N commandes |
| 1..* | 1 ou plusieurs | Une équipe a au moins 1 joueur |
| 2..5 | De 2 à 5 | Un polygone a 2 à 5 côtés |
| 3 | Exactement 3 | Un triangle a 3 sommets |
Exemple avec multiplicités
Exemple Complet — Bibliothèque
Diagramme complet : héritage, association, composition, dépendance et multiplicités.
UML → Python
Traduction directe de chaque notation UML en code Python.
Classe abstraite avec membre statique
from abc import ABC, abstractmethod
class Forme(ABC): # abstraite
nb_formes = 0 # statique
def __init__(self, couleur="rouge"):
self._couleur = couleur # protégé #
Forme.nb_formes += 1
@abstractmethod
def aire(self) -> float: ... # abstraite
def getCouleur(self): # concrète
return self._couleur
Composition ◆
class Maison:
def __init__(self, n):
# pièces créées DANS __init__
self.pieces = [Piece() for _ in range(n)]
Agrégation ◇
class Equipe:
def __init__(self):
self.joueurs = [] # liste vide
def ajouter(self, j):
# joueur externe injecté
self.joueurs.append(j)
Aide-mémoire
👁 Visibilité
| + | public |
| - | privé |
| # | protégé |
| ~ | package |
📐 Notations
| italique | abstrait |
| souligné | statique |
| «stéréotype» | guillemets |
| PascalCase | noms classes |
| camelCase | attributs/méth. |
🔗 Relations
| ——▶ | Association |
| ◇—— | Agrégation |
| ◆—— | Composition |
| ——▷ | Héritage |
| - -▷ | Réalisation |
| - -▶ | Dépendance |
🔢 Multiplicités
| 1 | exactement 1 |
| 0..1 | 0 ou 1 |
| * | 0 ou plusieurs |
| 1..* | 1 ou plusieurs |
| n..m | de n à m |