User Tools

Site Tools


2013_2014:s2:td:td_classes-code-associations:codes

Des modèles aux classes : CODES

Ces codes sont là pour vous aider. Ils ne sont pas LA solution. Beaucoup d'autres solutions sont possibles, mais il faut rigoureusement respecter les énoncés.

Code et associations "simples"

Voici un diagramme UML en conception.

Les objectifs de ces TDs sont de bien positionner la modélisation en UML de niveau conception relativement au codage !

Des codes vous sont donnés pour vous aider à comprendre et à ne pas perdre de temps. L'objectif n'est pas de vous apprendre à écrire des boucles ou des algorithmes, mais davantage de bien architecturer vos applications.

Association orientée : Multiplicité 1

Codes : etape 1

public class Professeur {
 
	private String nom;
	private String titre;
 
	public Professeur(String nom, String titre) {
		this.nom = nom;
		this.titre = titre;
	}
 
 
       //Pour que l'affichage d'un Professeur soit lisible. Cette méthode est appelée par défaut.
	public String toString() {
		return "Professeur [nom=" + nom + ", titre=" + titre + "]";
	}
 
 
 
}
public class Cours {
 
	private String intitule;
	private Professeur responsable;
	public Professeur getResponsable() {
		return responsable;
	}
 
	public void setResponsable(Professeur responsable) {
		this.responsable = responsable;
	}
 
	//Constructeur
	public Cours(String intitule, Professeur responsable) {
		this.intitule = intitule;
		this.responsable = responsable;
	}
 
 
        //Pour que l'affichage d'un cours soit "lisible"
	public String toString() {
		return "Cours [intitule=" + intitule + ", responsable=" + responsable +"]";
 
	}

Tests : etape 1

Pour éviter les confusions du dernier TD, voici un simple “main” qui permet de vérifier que vos codes “compilent” et s'“exécutent”. Nous essaierons de revenir sur les tests dans d'autres séances !!!
public class TestCours {
 
public static void main(String[] args) {
 
		System.out.println("===================== Etape 1 =================================");
		Professeur prof = new Professeur("Tournesol", "academicien");
		System.out.println("Professeur [nom=Tournesol, titre=academicien] = \n" + prof);
		Cours cBD = new Cours("BD", prof);
		System.out.println("Cours [intitule=BD, responsable=Professeur [nom=Tournesol, titre=academicien]] = \n" + cBD);
		System.out.println("=> Un même prof sur deux cours");
		Cours cAero = new Cours("aero", prof);
		System.out.println("Cours [intitule=aero, responsable=Professeur [nom=Tournesol, titre=academicien]] = \n" + cAero);
	}

Modèle : étape 2

Dans ce modèle, l'association apparaît aussi sous la forme d'un attribut (diagramme obtenu par reverse). Pour éviter cela, il faut sélectionner l'attribut, clique droit puis “show as association”

Code : étape 2

public class Cours {
 
	private String intitule;
	private Professeur responsable;
 
	public Professeur getResponsable() {
		return responsable;
	}
 
	public void setResponsable(Professeur p) {
		this.responsable = p;
	}
 
	public boolean aUnResponsable(){
		return (responsable != null);
	}
	//Constructeur
	public Cours(String intitule, Professeur responsable) {
		//this.intitule = intitule; 
		this(intitule); // Les codes précédents restent corrects mais on préfère ici une cascade. Uniquement pour les étudiants plus avancés.  
		this.responsable = responsable;
	}
 
	/*Constructeur sans le professeur responsable 
	 * puisque à présent il est possible de créer un cours sans responsable.
	*/
	public Cours(String intitule) {
		this.intitule = intitule;
	}
 
 
    //Pour que l'affichage d'un Cours soit lisible. Cette méthode est appelée par défaut.
	public String toString() {
		return "Cours [intitule=" + intitule + ", responsable=" + responsable +"]";
 
	}

Tests : étape 2

A Placer dans le main. Vous pouvez commenter l'étape précédente.

		/* Etape 2 */
		Professeur amina = new Professeur("AMINA", "missBahut");
		Cours cProfs = new Cours("Francais");
		System.out.println("Cours [intitule=Francais, responsable=null]  = " + cProfs);
		System.out.println("A un responsable (false) : " + cProfs.aUnResponsable());
		cProfs.setResponsable(amina);
		System.out.println("A un responsable (true) : " + cProfs.aUnResponsable());
		System.out.println("Cours [intitule=Francais, responsable=Professeur [nom=AMINA, titre=missBahut]]  =\n" + cProfs);

Association orientée : Multiplicité 0..*

Modèle

Code

Dans la classe **Cours**

Cette version n'est pas développée, elle doit être terminée
/* Version simple en générant un tableau... à terminer ... */
public class Cours {
 
	private Vacataire[] vacataires = new Vacataire[0];
}

Autre solution dans la classe cours

Placer bien vos attributs en début de définition de la classe.

N'oubliez pas import java.util.*;
ArrayList<Vacataire> vacataires = new ArrayList<Vacataire>();
 
	public void addVacataire(Vacataire v) {
		vacataires.add(v);
	}
 
	/**
	 * @param v : Vacataire à retirer de la liste
	 * @return boolean 
	 * Retire le vacataire v de la liste (exactement le même objet) si la collection contient cet élément.
	 * Renvoie vrai si la  collection contient l'element et La liste des vacataires est modifiée 
	 * sinon elle renvoie faux. 
	 */
	public boolean removeVacataire(Vacataire v) {
		return (vacataires.remove(v));
	}
 
    private String vacatairesToString() {
    	String vacatairesString = " ";
    	Iterator<Vacataire> it = vacataires.iterator();
    	while (it.hasNext()) {
    		vacatairesString += it.next().toString() + ";";
    	}
    	return "{ " + vacatairesString.substring(0, vacatairesString.length()-1)+ "}";
    }
 
	public String toString() {
		return "Cours [intitule=" + intitule + ", responsable=" + responsable
				+ ", vacataires=" + vacatairesToString()
				+ "]";
	}
 
Attention, le remove suppose que l'on sait comparer des Vacataires. Ici, comme le equals n'est pas redéfini, seuls des vacataires exactement les mêmes seront retirés au sens de l'égalité des pointeurs.
public class Vacataire  {
	private String nom;
 
	public Vacataire(String nom) {
		this.nom = nom;
	}
 
	@Override
	public String toString() {
		return "Vacataire [nom=" + nom + "]";
	}
 
 
}

Tests

		/* Etape 3 */
		Cours cBD = new Cours("BD");
		System.out.println("Cours [intitule=BD, responsable=null, vacataires={ } = \n" + cBD);
		Vacataire dolores = new Vacataire("Dolorès");
		Vacataire eric = new Vacataire("eric");
		System.out.println("=> Pas de retrait possible (false)  = " + cBD.removeVacataire(dolores));
		System.out.println("Et le cours n'est pas modifié = \n" + cBD);
		cBD.addVacataire(dolores);
		System.out.println("=> Ajout pris en compte ");
		System.out.println("Cours [intitule=BD, responsable=null, vacataires={  Vacataire [nom=Dolorès]}]\n" + cBD);
		System.out.println("=> Pas de retrait possible  de eric(false)  = " + cBD.removeVacataire(eric));
		System.out.println("=> Retrait pris en compte (true) = "+ cBD.removeVacataire(dolores));
		System.out.println("Cours [intitule=BD, responsable=null, vacataires={ }]\n" + cBD);
		System.out.println("=> Ajouts pris en compte = ");
		cBD.addVacataire(dolores);
		cBD.addVacataire(eric);
		System.out.println("Cours [intitule=BD, responsable=null, vacataires={  Vacataire [nom=Dolorès];Vacataire [nom=eric]}] \n" + cBD);
		System.out.println("=> Retrait eric pris en compte (true)= "+ cBD.removeVacataire(eric));
		System.out.println("Cours [intitule=BD, responsable=null, vacataires={  Vacataire [nom=Dolorès]}]\n" + cBD);
		cBD.addVacataire(eric);
		System.out.println("=> Retrait dolores pris en compte = "+ cBD.removeVacataire(dolores));
		System.out.println("Cours [intitule=BD, responsable=null, vacataires={  Vacataire [nom=eric]}]= \n" + cBD);

TRACE

Cours [intitule=BD, responsable=null, vacataires={ } = 
Cours [intitule=BD, responsable=null, vacataires={ }]
=> Pas de retrait possible (false)  = false
Et le cours n'est pas modifié = 
Cours [intitule=BD, responsable=null, vacataires={ }]
=> Ajout pris en compte 
Cours [intitule=BD, responsable=null, vacataires={  Vacataire [nom=Dolorès]}]
Cours [intitule=BD, responsable=null, vacataires={  Vacataire [nom=Dolorès]}]
=> Pas de retrait possible  de eric(false)  = false
=> Retrait pris en compte (true) = true
Cours [intitule=BD, responsable=null, vacataires={ }]
Cours [intitule=BD, responsable=null, vacataires={ }]
=> Ajouts pris en compte = 
Cours [intitule=BD, responsable=null, vacataires={  Vacataire [nom=Dolorès];Vacataire [nom=eric]}] 
Cours [intitule=BD, responsable=null, vacataires={  Vacataire [nom=Dolorès];Vacataire [nom=eric]}]
=> Retrait eric pris en compte (true)= true
Cours [intitule=BD, responsable=null, vacataires={  Vacataire [nom=Dolorès]}]
Cours [intitule=BD, responsable=null, vacataires={  Vacataire [nom=Dolorès]}]
=> Retrait dolores pris en compte = true
Cours [intitule=BD, responsable=null, vacataires={  Vacataire [nom=eric]}]= 
Cours [intitule=BD, responsable=null, vacataires={  Vacataire [nom=eric]}]

Association bi-directionnelle

Modèle

Codes

import java.util.*;
 
public class Etudiant {
 
 
	private String nom;
	private int niveau;
 
	Collection<Cours> cours = new ArrayList<Cours>();
 
	public Etudiant(String nom, int niveau) {
		this.nom = nom;
		this.niveau = niveau;
	}
 
	//Le choix de protected permet d'interdire l'utilisation de cette opération en dehors du package.
	// Et donc de "potentiellement" éviter une incohérence.
	// En phase de tests, il serait plus sage de vérifier que le cours a bien connaissance de l'étudiant.
	protected void addCours(Cours unCours) {
		cours.add(unCours);
	}
 
	protected void removeCours(Cours unCours) {
		cours.remove(unCours);
 
	}
 
    private String coursToString() {
    	String coursString = " ";
    	Iterator<Cours> it = cours.iterator();
    	while (it.hasNext()) {
    		coursString += it.next().getIntitule() + ";";
    	}
    	return "{ " + coursString.substring(0, coursString.length()-1)+ "}";
    }
 
 
	public String toString() {
		return "Etudiant [nom=" + nom + ", niveau=" + niveau + ", cours="
				+ coursToString() + "]";
	}
 
 
 
}

Dans la classe Cours

	Collection<Etudiant> etudiants  = new ArrayList<Etudiant>();
 
	// Attention on ne vérifie pas que l'étudiant n'est pas déjà référencé
	public void addEtudiant(Etudiant e){
		etudiants.add(e);
		e.addCours(this);
	}
 
	public boolean removeEtudiant(Etudiant e) {
		boolean retrait = etudiants.remove(e);
		if (retrait)
			e.removeCours(this);
		return retrait;
	}
    private String etudiantsToString() {
    	String etudiantsString = " ";
    	Iterator<Etudiant> it = etudiants.iterator();
    	while (it.hasNext()) {
    		etudiantsString += it.next().toString() + ";";
    	}
    	return "{ " + etudiantsString.substring(0, etudiantsString.length()-1)+ "}";
    }
 
 
	public String toString() {
		return "Cours [intitule=" + intitule + ", responsable=" + responsable
				+ ", vacataires=" + vacatairesToString()
				+ ", etudiants=" + etudiantsToString()
				+ "]";
	}

Tests

	System.out.println("===================== Etape 4 : Cours-Etudiant =================================");
		Etudiant boulard = new Etudiant("Boulard", 0);
		Etudiant nitchinsky = new Etudiant("Nitchinsky", 0);
		cBD = new Cours("BD");
		System.out.println("Cours [intitule=BD, responsable=null, vacataires={ }, etudiants={ }] \n ==" + cBD);
		System.out.println("=> Pas de retrait possible (false)  = " + cBD.removeEtudiant(boulard));
		System.out.println("=> Pas de retrait possible du cours dans etudiant mais pas d erreur " );
		System.out.println("Et le cours n'est pas modifié = \n ==" + cBD);
		cBD.addEtudiant(boulard);
		System.out.println("=> Ajout pris en compte ");
		System.out.println("Cours [intitule=BD, responsable=null, vacataires={ }, etudiants={  Etudiant [nom=Boulard, niveau=0, cours={  BD}]}] \n ==" + cBD);
		System.out.println("=> Pas de retrait possible  de nitchinsky(false)  = " + cBD.removeEtudiant(nitchinsky));
		System.out.println("=> Retrait pris en compte (true) = "+ cBD.removeEtudiant(boulard));
		System.out.println("Cours [intitule=BD, responsable=null, vacataires={ }, etudiants={ }]\n ==" + cBD);
		System.out.println("etudiant ne reference plus le cours :" + boulard);		
		System.out.println("=> Ajouts pris en compte = ");
		cBD.addEtudiant(boulard);
		cBD.addEtudiant(nitchinsky);
		System.out.println("Cours [intitule=BD, responsable=null, vacataires={ }, etudiants={  Etudiant [nom=Boulard, niveau=0, cours={  BD}];Etudiant [nom=Nitchinsky, niveau=0, cours={  BD}]}] \n ==" + cBD);
		System.out.println("===> un même etudiant dans plusieurs cours ");
		cProfs = new Cours("Francais");
		cProfs.addEtudiant(boulard);
		System.out.println("Boulars et nitchinsky \n ==" + cBD);
		System.out.println("Que Boulard \n ==" + cProfs);
    	System.out.println("=> Retrait Boulard pris en compte (true)= "+ cBD.removeEtudiant(boulard));
		System.out.println("Que nitchinsky \n ==" + cBD);

Composition

Code

public  abstract class Control {
 
	private String intitule;
	private double coeff;
 
	protected Control(String intitule, double coeff) {
		super();
		this.intitule = intitule;
		this.coeff = coeff;
	}
 
	public String toString() {
		return this.getClass().getSimpleName() + " [intitule=" + intitule + ", coeff=" + coeff + "]";
	}
}
public class DS extends Control {
 
	protected DS(String intitule, double coeff) {
		super(intitule, coeff);
	}
}
public class TD extends Control {
 
	protected TD(String intitule, double coeff) {
		super(intitule, coeff);
	}
 
}

Dans la classe Cours

 
	/*Constructeur de plus haut niveau
         * Un cours est automatiquement construit avec un TD et un DS avec des valeurs par défaut
         * Il faudrait ajouter des méthodes d'accès en lecture comme getTD
	*/
	public Cours(String intitule) {
		this.intitule = intitule;
		td = new TD("TD_"+ intitule,1);
		ds = new DS("DS_"+ intitule,1.5);
	}
 
 
	public String toString() {
		return "Cours [intitule=" + intitule + ", responsable=" + responsable
				+ ", vacataires=" + vacatairesToString()
				+ ", etudiants=" + etudiantsToString()
				+ td
				+ ds
				+ "]";
	}

Tests

System.out.println("===================== Etape 5 : Cours-TD/DS =================================");
 
		Cours cBD = new Cours("BD");
		System.out.println("=Cours [intitule=BD, responsable=null, vacataires={ }, etudiants={ }TD [intitule=TD_BD, coeff=1.0]DS [intitule=DS_BD, coeff=1.5]] \n ==" + cBD);
		Professeur prof = new Professeur("Tournesol", "academicien");
		cBD = new Cours("BD", prof);
		System.out.println("Cours [intitule=BD, responsable=Professeur [nom=Tournesol, titre=academicien], vacataires={ }, etudiants={ }TD [intitule=TD_BD, coeff=1.0]DS [intitule=DS_BD, coeff=1.5]]\n ==" + cBD);
 

Dans les codes la méthode coursAssociée n'a pas été définie ni d'ailleurs dans le modèle. Ici nous avons au niveau des codes orienté la relation. Le modèle devrait être revue pour refléter la réalité des codes.

Dans la figure ci-dessous, nous avons fait le choix de laisser ds visible à la fois comme une association et un attribut pour visualiser la construction interne du DS. Nous aurions pu faire de même pour le TD. Néanmoins, nous déconseillons cette double visualisation d'une même information qui crée de l'ambiguité. L'utilisation de la composition peut donner la même information, mais l'outil la perd lors du passage au code :-X

Classe d'association

Codes

public class Enseignant {
 
	String nom;
	public Enseignant(String nom) {
		this.nom = nom;
	}
 
	@Override
	public String toString() {
		return "Enseignant : " + nom + " ";
	}
 
}
public class Description {
	private int annee;
	private String section;
	public Enseignant responsable;
 
	public void setResponsable(Enseignant aResponsable) {
		this.responsable = aResponsable;
	}
 
	public Enseignant getResponsable() {
		return this.responsable;
	}
 
	protected int getAnnee() {
		return annee;
	}
 
	protected void setAnnee(int annee) {
		this.annee = annee;
	}
 
	protected String getSection() {
		return section;
	}
 
	protected void setSection(String section) {
		this.section = section;
	}
 
	@Override
	public String toString() {
		return "Description [annee=" + annee + ", section=" + section
				+ ", responsable=" + responsable + "]";
	}
 
}
public class Module {
 
	     private int maxDesc = 10;
		 Description[] description = new Description[maxDesc];
		 private int numberOfDescr = 0;
 
		public void addDescription(Description aDescription_d) {
			if (numberOfDescr==maxDesc)
				return;
			else {
				description[numberOfDescr]=aDescription_d;
				numberOfDescr++;
			}
		}
 
		public Enseignant getResponsable(int aAnnee, String aSection) {
			for (Description d : description) {
				if ((d!=null) && (d.getAnnee()==aAnnee) && (d.getSection()==aSection))
					return d.getResponsable();
			}
			return null;
		}
 
		@Override
		public String toString() {
			return "Module [ description="
					+ Arrays.toString(description) + ", numberOfDescr="
					+ numberOfDescr + "]";
		}
 
 
}

Tests

	Module mUML = new Module();
		Module mJAVA = new Module();
		Description d2014 = new Description();
		d2014.setAnnee(2014);
		d2014.setSection("s2T");
		Enseignant E1 = new Enseignant("profTrad");
		d2014.setResponsable(E1);
		mUML.addDescription(d2014);
		Description e2014 = new Description();
		e2014.setAnnee(2014);
		e2014.setSection("s2A");
		Enseignant E2 = new Enseignant("ProfAlt");
		e2014.setResponsable(E2);
		mUML.addDescription(e2014);
		System.out.println(mUML);
		System.out.println(mJAVA);		
 
		System.out.println(mUML.getResponsable(2014, "s2T"));
		System.out.println(mUML.getResponsable(2014, "s2A"));
		System.out.println("-----------");
		System.out.println("pas de tel cours");
		System.out.println(mUML.getResponsable(2015, "s2A"));
		if (mJAVA.getResponsable(2015, "s2A") == null)
			System.out.println("pas de tel cours");
2013_2014/s2/td/td_classes-code-associations/codes.txt · Last modified: 2014/04/15 13:44 by blay