EPSI B3 - Java

Cours de 3ième année EPSI Bordeaux : les fondamentaux du langage Java

Exercices

Exercice - Programme simple

Testez le programme Java suivant :

public class PremierProgramme {

	public static void main(String[] args) {
		String message = "Bonjour";
		System.out.println(message);
	}

}

Pour fonctionner, ce programme doit se trouver dans un fichier PremierProgramme.java dans le répertoire des sources du projet.

System.out représente la sortie standard du programme.

Exercice à rendre - les nombres premiers

On souhaite connaître le nombre de nombres premiers entre 1 et 1000. En mathématique, un nombre premier est un nombre qui n’est divisible que par 1 et lui-même.

Complétez la fichier NombrePremier.java ci-dessous :

public class NombrePremier {

	public static void main(String[] args) {
		int nbNombresPremiers = 0;

		// TODO Trouver le nombre de nombres premiers entre 1 et 1000

		System.out.println(nbNombresPremiers);
	}

}

Chapitres de référence :

Exercice à rendre - afficher les nombres premiers

On souhaite afficher les nombres premiers entre 1 et 1000. En mathématique, un nombre premier est un nombre qui n’est divisible que par 1 et lui-même.

Complétez la fichier AffichageNombrePremier.java ci-dessous :

import java.util.ArrayList;
import java.util.List;

public class AffichageNombrePremier {

	public static void main(String[] args) {
		// List<Integer> représente une liste d'entiers.
		List<Integer> nombresPremiers = new ArrayList<>();

		// TODO trouver les nombres premiers entre 1 et 1000 et les ajouter dans la liste.
		// L'ajout dans la liste se fait avec la méthode nombresPremiers.add().

		for (int i : nombresPremiers) {
			System.out.println(i);
		}
	}

}

Chapitres de référence :

Exercice à rendre - afficher les nombres premiers (version 2)

Reprenez l’exercice précédent. On peut redéfinir un nombre premier comme : un nombre qui n’est pas divisible par un autre nombre premier sauf 1 et lui-même.

Améliorez l’implémentation précédente en utilisant la liste des nombres premiers déjà trouvés pour déterminer si le nombre courant est premier.

Chapitres de référence :

Exercice à rendre - La classe Rectangle

Implémentez une classe Rectangle. Cette classe doit définir les méthodes suivantes :

  • public double getLongueur()

  • public void setLongueur(double valeur)

  • public double getLargeur()

  • public void setLargeur(double valeur)

  • public double getPerimetre()

  • public double getAire()

  • public boolean isCarre()

  • public void transpose()

Pour rappel, le périmètre d’un rectangle est :

périmètre = (longueur + largeur) x 2

Pour rappel, l’aire d’un rectangle est :

aire = longueur x largeur

Un rectangle est un carré si sa longueur est égale à sa largeur. La méthode transponse intervertit la largeur et la longueur.

Un fois implémentée, votre classe doit pouvoir être utilisée dans le programme DemoRectangle.java ci-dessous :

public class DemoRectangle {

	public static void main(String[] args) {

		Rectangle r = new Rectangle();
		r.setLargeur(10);
		r.setLongueur(20);

		System.out.printf("Un rectangle de largeur %.2f et de longueur %.2f\n", r.getLargeur(), r.getLongueur());
		System.out.printf("Le perimettre de ce rectangle est %.2f\n", r.getPerimetre());
		System.out.printf("L'aire de ce rectangle est %.2f\n", r.getAire());
		System.out.println(r.isCarre() ? "Ce rectangle est un carre" : "Ce rectangle n'est pas un carre");

		r.transpose();
		System.out.printf("Un rectangle de largeur %.2f et de longueur %.2f\n", r.getLargeur(), r.getLongueur());
		System.out.printf("Le perimettre de ce rectangle est %.2f\n", r.getPerimetre());
		System.out.printf("L'aire de ce rectangle est %.2f\n", r.getAire());
		System.out.println(r.isCarre() ? "Ce rectangle est un carre" : "Ce rectangle n'est pas un carre");

		r.setLargeur(r.getLongueur());
		System.out.printf("Un rectangle de largeur %.2f et de longueur %.2f\n", r.getLargeur(), r.getLongueur());
		System.out.printf("Le perimettre de ce rectangle est %.2f\n", r.getPerimetre());
		System.out.printf("L'aire de ce rectangle est %.2f\n", r.getAire());
		System.out.println(r.isCarre() ? "Ce rectangle est un carre" : "Ce rectangle n'est pas un carre");
	}

}

Chapitres de référence :

Exercice à rendre - La classe Phrase

Implémentez la classe Phrase. Cette classe permet de créer une chaîne de caractères en ajoutant des mots qui seront séparés par un séparateur. Par défaut, le séparateur est le caractère espace, mais il peut être changé.

La classe Phrase doit permettre de :

  • ajouter un mot

  • ajouter une série de mots (nombre de paramètres variable)

  • ajouter un mot en le répétant n fois (on indique le mot et le nombre de fois qu’il faut le répéter)

  • changer le séparateur qui peut être soit une chaîne de caractères soit un seul caractère

  • la méthode public String toString() permet de récupérer la phrase sous la forme d’une chaîne de caractères. Cette chaîne doit être terminée par un point.

  • connaître le nombre de lettres dans la phrase

Le code suivant :

Phrase phrase = new Phrase();
phrase.ajouter("Une");
phrase.ajouter("classe");
phrase.ajouter("pour");
phrase.ajouter("ajouter");
phrase.ajouter("des mots");
phrase.setSeparateur(" et encore ");
phrase.ajouter("des mots", 3);
phrase.setSeparateur(' ');
phrase.ajouter("toujours", "et", "encore");

System.out.println(phrase);
System.out.println(phrase.getNbLettres());

doit produire sur la sortie standard

Une classe pour ajouter des mots et encore des mots et encore des mots et encore des mots toujours et encore.
88

Indication

On ne peut pas parcourir directement une chaîne de caractères, par contre on peut obtenir un tableau de caractères à partir d’une chaîne avec la méthode toCharArray.

String helloWorld = "Hello world!";
for (char c : helloWorld.toCharArray()) {
  // ...
}

Pour savoir si un caractère est une lettre, on utilise la méthode static Character.isAlphabetic.

Chapitres de référence :

Exercice à rendre - Le jeu du pendu

On souhaite réaliser un programme en ligne de commande pour jouer au jeu du pendu.

Vous devez implémenter la classe JeuDuPendu. Elle possède :

  • un constructeur pour lui passer le mot à trouver

  • la méthode proposer qui attend une lettre (char) en paramètre et qui retourne true si la lettre est présente dans le mot à trouver

  • la méthode getNbTentativesRestantes qui indique le nombre de tentatives restantes. Ce nombre diminue chaque fois qu’on propose une lettre qui n’est pas dans le mot

  • la méthode isPartieGagnee qui indique si on a trouvé toutes les lettres du mot.

  • la méthode isPartieTerminee qui indique si la partie est terminée. Une partie est terminée si on a gagné ou s’il ne reste plus de tentative.

  • la méthode getMotMasque qui retourne sous forme de chaîne de caractères le mot à trouver. ATTENTION, les lettres non encore trouvées sont remplacées par _.

  • la méthode getSolution qui retourne le mot qu’il faut trouver.

Si votre implémentation est complète, vous pourrez la tester avec la classe DemoJeuDuPendu ci-dessous :

import java.util.Scanner;

public class DemoJeuDuPendu {

	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		JeuDuPendu jeuDuPendu = new JeuDuPendu("feuille");

		do {
			String motMasque = jeuDuPendu.getMotMasque();
			int nbTentativesRestantes = jeuDuPendu.getNbTentativesRestantes();
			System.out.printf("Le mot : %s\n", motMasque);
			System.out.printf("Proposez une lettre (il reste %d tentatives) : ", nbTentativesRestantes);
			String ligne = scanner.nextLine();
			if (ligne.length() != 1) {
				System.out.println("Vous devez saisir une seule lettre!");
				continue;
			}
			char lettre = ligne.charAt(0);
			if (! jeuDuPendu.proposer(lettre)) {
				System.out.println("Cette lettre n'est pas présente dans le mot à trouver.");
			}
		} while(! jeuDuPendu.isPartieTerminee());

		if (jeuDuPendu.isPartieGagnee()) {
			System.out.println("Bravo, vous avez gagné !");
		} else {
			System.out.printf("Vous avez perdu. Le mot à trouver était %s.\n", jeuDuPendu.getSolution());
		}
	}
}

Chapitres de référence :

Exercice bonus à rendre - Les constructeurs pour la classe Phrase

En reprenant la classe Phrase, ajoutez les constructeurs suivants :

// constructeur sans paramètre
Phrase phrase = new Phrase();
phrase.ajouter("Bonjour", "le", "monde");
System.out.println(phrase); // Bonjour le monde.

// constructeur pour indiquer quel caractère fini la phrase
Phrase phraseInterrogative = new Phrase(Phrase.INTERROGATION);
phraseInterrogative.ajouter("Ça", "va");
System.out.println(phraseInterrogative); // Ça  va ?

Phrase phraseExclamative = new Phrase(Phrase.EXCLAMATION);
phraseExclamative.ajouter("Oui");
System.out.println(phraseExclamative); // Oui !

Phrase phraseDeclarative = new Phrase(Phrase.DECLARATION);
phraseDeclarative.ajouter("C'est", "bien");
System.out.println(phraseDeclarative); // C'est bien.

// constructeur pour indiquer quel caractère fini la phrase
// et passer un nombre quelconque de mots à la phrase
phrase = new Phrase(Phrase.INTERROGATION, "Et", "ensuite");
System.out.println(phrase); // Et ensuite ?

Ajoutez également des méthodes de classe (méthodes statiques) pour créer directement une Phrase selon son type :

phrase = Phrase.interrogation("Comment", "allez", "vous");
System.out.println(phrase); // Comment allez vous ?

phrase = Phrase.exclamation("Dormez");
System.out.println(phrase); // Dormez !

phrase = Phrase.declaration("Brian", "est", "dans", "la", "cuisine");
System.out.println(phrase); // Brian est dans la cuisine.

Chapitres de référence :

Exercice à rendre - Les constructeurs pour la classe Rectangle

Reprenez la classe Rectangle et ajoutez les constructeurs suivants :

  • Un constructeur qui attend la largeur et la longueur en paramètre

  • Un constructeur qui attend une seule valeur pour créer un carré

  • Un constructeur qui attend un Rectangle en paramètre et qui crée un rectangle avec la même largeur et longueur que celui passé en paramètre.

Testez vos implémentations en ajoutant du code de test dans la classe DemoRectangle.

Chapitre de référence :

Exercice à rendre - Gestion des formations

On souhaite représenter un système de gestion des formations. Chaque formation est représentée par son nom et la liste des modules qui la composent.

Créez les classes Formation et ModuleFormation. Un module de formation a un nom, une description, un nombre maximum de stagiaires acceptés et une durée en heures pleines. Une Formation a la propriété duree qui correspond à la somme des heures des modules qui la composent et la propriété nbStagiaires (minimum du nombre autorisé de stagiaires des modules qui la composent).

Il existe différents types de module de formation :

  • le type Cours qui dispose d’un numéro de salle

  • le type Tutoriel qui est représenté par un lien sur une vidéo en ligne. Il n’y a pas de limite au nombre de stagiaires pouvant suivre un tutoriel. Pour simplifier, vous pouvez considérer que la limite est fixée arbitrairement à 1000 stagiaires.

  • le type Projet qui est défini par le nombre de groupes et le nombre maximum de stagiaires dans un groupe. Le nombre de stagiaires maximum est donc le produit du nombre de groupes et du nombre de personnes par groupe.

Par exemple, si la formation Programmer en Java comprend :

  • Un cours de 20h accueillant 25 stagiaires maximum

  • Un tutoriel en ligne de 4h

  • Un projet de 30h avec 4 groupes de 5 personnes (soit 5 x 4 = 20 stagiaires)

Alors la formation Programmer en Java dure 54h et est disponible pour 20 stagiaires au maximum.

Testez votre implémentation avec une classe DemoFormation contenant une méthode main. Vérifiez que vous obtenez bien la durée et le nombre de stagiaires attendus pour une formation.

Chapitres de référence :

Exercice à rendre - Le rectangle (suite)

Reprenez la classe Rectangle. On veut pouvoir comparer deux rectangles entre eux. Deux rectangles sont identiques s’ils ont la même longueur et la même largeur.

Modifiez la classe DemoRectangle pour tester vos ajouts.

Chapitres de référence :

Exercice à rendre - Figures géométriques (1/3)

On souhaite créer des classes Java qui permettent de représenter et de manipuler des figures géométriques.

Une figure est une représentation abstraite d’une forme géométrique. Parmi les figures géométriques, on distingue :

  • Le rectangle qui est défini par sa longueur et sa largeur

  • Le disque qui est défini par son rayon

Pour chaque type de figure, il est possible de connaître son périmètre et son aire.

Pour un rectangle

périmètre = (longueur + largeur) x 2
aire = longueur x largeur

Pour un disque

périmètre = 2 x π x rayon
aire = π x rayon²

Note

La valeur de π est donnée en Java par la constante Math.PI

Reprenez l’implémentation de la classe Rectangle et implémentez les classes Disque et Figure. Toutes ces classes doivent déclarer les méthodes getPerimetre() et getAire().

Créez une classe DemoFiguresGeometrique avec une méthode main pour tester votre implémentation.

Chapitres de référence :

Exercice à rendre - Figures géométriques (2/3)

Reprenez l’exercice précédent et ajoutez la classe FigureComposee. Cette classe est une figure qui contient une liste de figures. Son périmètre vaut la somme des périmètres de toutes ses figures. Son aire vaut la somme des aires de toutes ses figures.

Implémentez la classe FigureComposee. Déclarez dans cette classe une méthode ajouter pour ajouter une nouvelle figure à cette figure composée.

Modifiez la classe DemoFigureGeometrique pour tester votre nouvelle classe.

Note

Une FigureComposee doit aussi pouvoir être composée d’autres FigureComposee. Dans les modèles de conception (design patterns), on appelle ce type de classe un composite. On trouve souvent ce type de représentation : dans un système de fichiers, un répertoire peut être représenté comme un type de fichier particulier qui peut contenir des fichiers ou des répertoires.

Chapitres de référence :

Exercice à rendre - Figures géométriques (3/3)

On veut pouvoir comparer deux objets Figure entre eux. Deux figures sont identiques si elles ont le même périmètre et la même aire.

Modifiez la classe DemoFigureGeometrique pour tester vos ajouts.

Chapitres de référence :

Exercice à rendre - Figures géométriques / les exceptions (1/4)

Modifier les classes Rectangle et Disque. Il ne doit pas être possible de donner une valeur négative pour la longueur, la largeur et le rayon à la construction des objets et sur les méthodes setter.

Utiliser l’exception IllegalArgumentException pour signaler qu’une valeur négative est interdite. Il s’agit d’un unchecked exception utilisée pour signaler un paramètre invalide.

Chapitre de référence :

Exercice à rendre - Figures géométriques / les exceptions (2/4)

Si ce n’est pas déjà le cas, déclarez une méthode ajouter dans la classe FigureComposee pour ajouter une Figure dans la figure composée. Afin d’éviter une relation cyclique, il n’est pas possible d’ajouter une figure composée à elle-même. Dans ce cas, la méthode ajouter doit produire une exception du type FigureInterditeException.

Créez la classe FigureInterditeException et modifiez la méthode ajouter de FigureComposee pour appliquer cette règle.

Faites évoluer les classes existantes afin qu’elles compilent toujours.

Chapitre de référence :

Exercice à rendre - Figures géométriques / les exceptions (3/4)

Étant donnée le programme suivant :

 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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
package geometrie;

import java.util.Scanner;

public class ApprentissageFiguresGeometriques {

	private FigureComposee figure = new FigureComposee();
	private Scanner scanner = new Scanner(System.in);

	public static void main(String[] args) {
		new ApprentissageFiguresGeometriques().start();
	}

	public void start() {
		while(afficherMenu()) {
			print();
			print("Votre nouveau choix");
		}
	}

	private boolean afficherMenu() {
		print("1) Ajouter un rectangle");
		print("2) Ajouter un disque");
		print("3) Afficher le perimetre et l'aire");
		print("Autre chiffre pour quitter");
		switch (scanner.nextInt()) {
		case 1:
			creerRectangle();
			return true;
		case 2:
			creerDisque();
			return true;
		case 3:
			afficherPerimetreEtAire();
			return true;
		default:
			print("Au revoir");
			return false;
		}
	}

	private void creerRectangle() {
		print("Quelle est la largeur du rectangle ?");
		double longueur = scanner.nextDouble();
		print("Quelle est la longueur du rectangle ?");
		double largeur = scanner.nextDouble();

		Rectangle r = new Rectangle(largeur, longueur);
		figure.ajouter(r);
		printf("Rectange de largeur %.04f et de longueur %f", r.getLargeur(), r.getLongueur());
		printf("Ce rectangle a un perimetre de %.04f et une aire de %.04f", r.getPerimetre(), r.getAire());
	}

	private void creerDisque() {
		print("Quel est le rayon du disque ?");
		double rayon = scanner.nextDouble();

		Disque d = new Disque(rayon);
		figure.ajouter(d);
		printf("Disque de rayon %.04f", d.getRayon());
		printf("Ce disque a un perimetre de %.04f et une aire de %.04f", d.getPerimetre(), d.getAire());
	}

	private void afficherPerimetreEtAire() {
		printf("Perimetre total : %.04f", figure.getPerimetre());
		printf("Aire totale : %.04f", figure.getAire());
	}

	private void print() {
		System.out.println();
	}

	private void print(String message) {
		System.out.println(message);
	}

	private void printf(String message, Object ... params) {
		System.out.printf(message, params);
		System.out.println();
	}

}

Vous pouvez télécharger directement le fichier ApprentissageFiguresGeometriques.java

Modifiez ce programme pour qu’il gère les exceptions de type IllegalArgumentException si jamais l’utilisateur saisit une valeur négative pour la longueur, la largeur ou le rayon.

Le programme ne doit pas planter. Il doit indiquer à l’utilisateur qu’il a fait une erreur et lui permettre de continuer à utiliser l’application.

Chapitre de référence :

Exercice bonus - Figures géométriques / les exceptions (4/4)

Pour le programme précédent, si vous saisissez autre chose qu’un nombre, le programme plante car les méthodes nextInt et nextDouble de la classe Scanner lancent alors une InputMismatchException.

Modifiez le programme précédent pour qu’il gère élégamment les erreurs de saisie de l’utilisateur. Par exemple, il peut signaler que la saisie n’est pas correcte et proposer une nouvelle tentative à l’utilisateur.

Astuce

Attention, lorsqu’un objet de la classe Scanner ne peut pas lire une donnée qui est au mauvais format, il jette une exception InputMismatchException et il conserve la valeur saisie dans une zone tampon. Cela signifie que les appels suivants aux méthodes de Scanner vont relire la même valeur ! Pour vider la zone tampon, il suffit de lire la donnée invalide sous la forme d’une chaîne de caractère en appelant la méthode next() :

scanner.next();

Chapitres de référence :

Exercice à rendre - La gestion d’un catalogue (1/3)

On désire mettre en place un outil pour la gestion d’articles dans un catalogue.

Important

L’objectif de cet exercice et des suivants est de vous inciter à réaliser une conception objet d’une application. Il serait sans doute possible de réaliser ces exercices en codant une ou plusieurs méthodes avec des centaines de lignes de code. Mais ce type d’implémentation serait maladroite en Java et surtout absolument pas évolutive.

Essayez de mettre en pratique le principe SOLID de la single responsability : une classe doit avoir une responsabilité unique dans un programme. Pour vous guider, les éléments en gras dans le texte représentent des responsabilités différentes qui devaient très certainement être implémentées dans des classes différentes.

Un catalogue est composé d’un ensemble d’articles. Un article a un code, un titre et une note metascore (nombre entier sur 100). Mais il a aussi des caractéristiques qui dépendent du type de l’article :

  • un film est un article qui a en plus un réalisateur et une affiche. Pour faire simple, l’affiche du film est représentée par une URI sur le web. Par exemple :

    https://static.cotecine.fr/tb/Affiches/450x450/ffffff/LES+7+SAMOURAIS.JPG
    

    Plutôt que de représenter l’adresse de l’affiche sur la forme d’une String, vous pouvez utiliser les classes Java URL ou URI.

  • une série tv est un article qui a en plus un distributeur et un nombre de saisons.

  • un jeu vidéo est un article qui a en plus un studio de développement et un niveau dans la classification PEGI : PEGI 3, PEGI 7, PEGI 12, PEGI 16 et PEGI 18. Vous pouvez représenter la classification PEGI avec une énumération en Java (Cf. Les énumérations).

Créez les classes pour représenter ce domaine. Placez ces classes dans le package catalogue de votre projet.

Exercice à rendre - La gestion d’un catalogue (2/3)

On souhaite implémenter un module pour charger les données d’un catalogue. Les données seront chargées à partir d’un fichier texte dans un format proche du format CSV.

Attention, nous souhaitons garantir une indépendance de ce module avec les autres modules que nous pourrions implémenter plus tard. Vous devez donc vous assurer que la classe responsable de charger le catalogue implémente l’interface ImporteurCatalogue :

package catalogue.io;

import java.io.IOException;
import catalogue.Catalogue;

public interface ImporteurCatalogue {

	Catalogue importer() throws IOException;

}

Vous pouvez télécharger directement le fichier ImporteurCatalogue.java

Voici un exemple de fichier à traiter. Chaque ligne représente un article en séparant les informations par un point-virgule. La ligne indique, le code, le titre, la note metascore, le type de l’article (film, serie, jeu) puis les informations spécifiques à chaque type d’article.

exemple de fichier de catalogue
F0001;Les sept samouraïs;98;film;Akira Kurosawa;https://static.cotecine.fr/tb/Affiches/450x450/ffffff/LES+7+SAMOURAIS.JPG
S0012;The Strain;70;serie;FX;4
JV010;Mass effect;89;jeu;Bioware;PEGI18

Pour lire un fichier, il existe plusieurs solutions en Java. La solution la moins performantes (mais la plus facile à coder) consiste à appeler la méthode de classe Files.readAllLines. Vous pouvez vous reporter au chapitre Les entrées/sorties pour en savoir plus.

Pour l’analyse d’une ligne, vous pouvez utiliser la méthode split de la classe String pour découper la chaîne de caractères en tableau en utilisant le point-virgule comme séparateur :

String[] colonnes = ligne.split(";");
// La première colonne est accessible part colonnes[0], la seconde
// colonne par colonnes[1], etc.

Écrivez une programme qui demande un chemin de fichier à l’utilisateur pour ensuite charger le catalogue. Si le chargement échoue avec une exception, affichez vos excuses à l’utilisateur ainsi que le message de l’exception.

Exercice à rendre - La gestion d’un catalogue (3/3)

On souhaite implémenter un module pour exporter le catalogue au format HTML.

Pour l’exemple de catalogue donné à l’exercice précédent, le résultat de l’export HTML sera :

<!DOCTYPE html>
<html lang="fr">
<head>
  <meta charset="utf-8">
  <title>Catalogue</title>
</head>
<body>

<h1>Catalogue</h1>

<article>
  <h2>Les sept samouraïs</h2>
  <p>Un film de Akira Kurosawa (metascore : 98)</p>
  <img src="https://static.cotecine.fr/tb/Affiches/450x450/ffffff/LES+7+SAMOURAIS.JPG" alt="affiche">
</article>

<article>
  <h2>The Strain</h2>
  <p>Une série FX en 4 saisons (metascore : 70)</p>
</article>

<article>
  <h2>Mass effect</h2>
  <p>Un jeu vidéo de Bioware (PEGI-18 et metascore : 89)</p>
</article>

</body>
</html>

Attention, nous souhaitons garantir une indépendance du module d’export. Vous devez donc vous assurer que la classe responsable d’exporter le catalogue au format HTML implémente l’interface ExporteurCatalogue :

package catalogue.io;

import java.io.IOException;
import catalogue.Catalogue;

public interface ExporteurCatalogue {

	void exporter(Catalogue catalogue) throws IOException;

}

Vous pouvez télécharger directement le fichier ExporteurCatalogue.java

L’export consiste à écrire le début du fichier HTML puis, pour chaque article d’écrire une balise <article> avec les informations de l’article et enfin, écrire la fin du fichier HTML.

Nous ne pouvons pas inclure une méthode toHTML dans notre classe Article ou une de ces sous-classes pour réaliser l’écriture de la balise <article>. Cela ne serait pas conforme au principe de single responsability. Nous ne pouvons pas non plus nous contenter de coder la procédure d’export dans une seule méthode : ce code ne serait pas très évolutif.

Pour réaliser l’export, vous devrez créer une interface ExporteurArticle. Cette interface sera implémentée par trois classes spécialisées : une pour l’export de film, une pour l’export de série et une pour l’export de jeu.

Créez également une classe ExporteurArticleFabrique. Cette classe agira comme une fabrique.

Note

Une fabrique est un modèle de conception (design patterns) couramment utilisé dans la programmation orientée objet. Il s’agit d’une classe dont la responsabilité est de créer des objets sans que le reste de l’application ne connaisse le type exact des objets créés.

Pour en savoir plus, vous pouvez consulter l’article Wikipedia dédié à ce modèle de conception :

https://fr.wikipedia.org/wiki/Fabrique_(patron_de_conception)

L’architecture générale de l’export peut être schématisée de la manière suivante :

_images/exporteur_article.png

Ce schéma n’est pas complet, par exemple, il manque certainement des méthodes. À vous de vous inspirer de ce schéma pour développer le module d’export.

Écrivez un programme qui demande à l’utilisateur d’indiquer le chemin d’un fichier de catalogue à charger et le chemin d’un fichier HTML à produire. Le programme doit alors charger le catalogue et produire le fichier HTML d’export.