Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feedback #1

Open
wants to merge 5 commits into
base: feedback
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
[![Review Assignment Due Date](https://classroom.github.com/assets/deadline-readme-button-24ddc0f5d75046c5622901739e7c5dd533143b0c8e959d652212380cedb1ea36.svg)](https://classroom.github.com/a/iqalO_EZ)
# Simulation de Vélo
Dans ce TP, vous réalisez des exercices sur les **patrons de conception**[^1] à l'aide d'une application simple qui simule, d'une manière très approximative, le fonctionnement d'un vélo.

Expand Down
51 changes: 50 additions & 1 deletion Rapport.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,70 @@
# Compte Rendu du TP 1 : Patrons de Conceptions

Noms des étudiants du binôme :
Noms des étudiants du binôme : MINTCHUENG KARELLE

## Exercices 1

Le modèle reflète le Patron de conception *Composite* le 'MobileObject' agit en tant que Composant, qui définit une interface pour les objets dans la composition
le 'Vehicle' joue le rôle de composite car elle stocke des composants enfants (instances de 'MobileObject') et implémente l'interface 'MobileObject'.

La méthode 'getVelocity()' n'as plus besion d'être écrite à nouveau car la classe 'Vehicle' fournit déjà une implémentation qui calcule la vitesse comme
une moyenne pondérée des vitesses de ses composants, ce qui est le comportement désiré pour 'TagAlongBike'
La methode 'getMasse()' n'a pas non plus besoin d'être écrite car l'implémentation heritée de 'Vehicle' calcule déjà la masse en sommant les masses de tous les composants.

## Exercices 2

Le Patron de conception utilisé par la méthode 'getVelocity()' de la classe 'Vehicle' est le patron de conception itérateur pour parcourir les composants d'un véhicule , un
itérateur est une interface qui permet de parcourir une collection élement par élement, sans exposer les details de la collection sous-jacente.

Avantage du patron itérateur : *Abstraction* : l'itérateur cache la complexité de parcours de la structure de données sous-jacente. ce qui permet d'utiliser le même code pour
parcourir différents types de collections sans se soucier de leur implémentation interne.
*Découplage* : Il découple les algorithmes des structures de données sur lesquelles ils opèrent ce qui améliore la maintenance et la réutilisation du code.
*Contrôle* : il fournit un contrôle sur le processus de parcours, ce qui peut être utilisé pour les opérations spécifiques comme l'insertion ou la suppression pendant l'itération

La modification de 'Set' à 'List' n'implique pas nécessairement une modification de la méthode 'getVelocity()' parce que les deux implémentations fournissent un itérateur via la méthode 'iterator()' utilisée dans la méthode actuelle. Cependant il est à noté que
la 'List' maintient l'ordre des élements, tandis que 'Set' ne le fait pas

## Exercices 3

Les étapes de la creation du singleton Clock sont les suivantes :
-Modifier le constructeur de la classe 'Clock' pour le rendre privé ce qui empêche l'instanciation directe de la classe depuis l'extérieur et assure que la classe ne peut être instanciée qu'à l'intérieur de celle-ci
-Ajouter une propriété privée dans la classe 'Clock' pour stocker l'unique instance de la classe. Cette instance est généralement initialisée directement lors de la déclaration ou plus tardivement dans la méthode statique 'getInstance()'
-Créer une méthode publique statique 'getInstance' qui retourne l'unique instance de la classe
-Remplacer toutes les instanciations directes de la classe 'Clock' par des appels à 'Clock.getInstance' ce qui va nous permettre de garantir que tous les composants utilisent la même instance pour l'horloge ce qui va permettre une synchronisation à travers toute l'application.

## Exercices 4

- Non 'Bike' et 'Wheel' n'appartiennent pas au même paquetage car 'bike' appartient au paquage Cycling et 'Wheel ' appartient au paquage transport
- La classe 'Wheel' depend de la classe 'Bike' pour obtenir la force de poussée via la méthode 'getPush()' il s'agit d'une méthode directe et bidirectionnelle car 'Bike' a des références à ses roues
et 'Wheel' à une référence à 'Bike' il s'agit d'une mauvaise pratique car il s'agit d'une dépendance cyclique entre 'Bike' et 'Wheel'
ce qui crée un couplage fort entre les deux classes du fait que, un changement dans l'une peut affecter directement l'autre, ce qui rend le système fragile et difficile à évoluer
- 'Bike' est utilisée par 'Wheel' pour calculer la vitesse de la roue via la méthode 'getPush'
- Oui, il existe déjà une abstraction de la classe 'Bike' qui est la classe 'Vehicle'(puisque 'Bike' etend 'Vehicle'). la méthode 'hetPush()' utilisée par 'Wheel' n'est pas astraite dans 'Vehicle', mais
pourrait être ajoutée en tant que méthode abstraite à 'Vehicle' ou en tant qu'interface séparée
- L'abstraction 'Vehicle' se trouve dans le paquetage transport
- Pour casser la dépendance cyclique, on pourrait introduire une interface, par exemple 'PushProvider', qui aurait une méthode 'getPush()'.'Bike' implémenterait cette interface ensuite, 'Wheel' ne dépendrait plus de 'Bike' directement, mais plutôt de l'interface 'PushProvider'

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Pour quoi introduire une nouvelle interface alors que Vehicle existe déjà ?
  • Il aura fallu passer par la classe Vehicle pour éviter de charger le code avec des nouveaux types.



## Exercices 5


## Exercices 6

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Réalisation manquante dans le code.


La différence entre la méthode de fabrique (Factory method) et le singleton est le suivant :
- Singleton : assurequ'une classe n'a qu'une seule instance et fournit un point d'accès global à cette instance ce qui est utile pour les ressources qui doivent être partagées, comme
une horloge
- La méthode fabriqueb: permet de creer des objets sans spécifier la classe exacte de l'objet qui ser crée ce qui permet de centraliser la logique de création des instances, offrant ainsi plus de flexibilité pour changer le type d'objets
crées sans changer le code qui utilise ces objets.

## Exercices 7

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Réalisation manquante de décorateur !


## Exercices 8

-Le Patron de conception de la classe context avec ServiceLoader suit le patron de conception FACADE car en encapsulant la complexité de 'ServiceLoader' derrière une interface simplifiée, 'context' rend l'utilisation des services plus accessible et plus

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Le code ne marche pas à cause de constructeur sans paramétre manquant.

simple pour les utilisateurs. Ce qui va permettre de centraliser la création et la gestion des instances, facilitant ainsi la maintenance et l'évolution de l'application.
-Oui nous pouvons avoir plusieurs lignes dans le fichier de services "fr.polytech.sim.cycling.Bike". Chaque ligne dans ce fichier va correspondre à une implémentation différente du type de service spécifié.'ServiceLoader' les utilisera pour charger toutes les implémentationsdisponibles du service
l'utilisation de 'injectAll' va permettre d'itéree sur toutes les instances disponibles pour le type de service demandé

## Exercices 9
-La méthode "injectAll()" de la classe 'context' retourne un 'Iterator', ce qui correspondant au patron de conception Iterateur. Ce patron permet d'accéder séquentiellement aux élements d'une collection sans exposer ses représentations sous-jacentes.
Elle va fournir une façon standard de parcourir des collectionsnet est utilisé dans la bibliothèque standard java pour parcourir tout objet implémentant l'interface 'Iterable'
18 changes: 17 additions & 1 deletion src/main/java/fr/polytech/sim/Clock.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,24 @@
* A clock used to synchronize simulations.
*/
public class Clock {
private final int time = new Random().nextInt(25);

private static final Clock instance = new Clock();

private final int time;

// Constructeur privé
private Clock(){
this.time = new Random().nextInt(25);
}

/**
* Acces à l'instance unique de l'horloge
* @return l'instance singleton de clock
*/

public static Clock getInstance(){
return instance;
}
/**
* Random integer between 0 and 24 inclusive.
*/
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/fr/polytech/sim/cycling/Bike.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package fr.polytech.sim.cycling;

import fr.polytech.sim.transport.Vehicle;
import fr.polytech.sim.transport.PushProvider;

/**
* Abstract bike.
*/
public abstract class Bike extends Vehicle {
public abstract class Bike extends Vehicle implements PushProvider {

@Override
public double getPush() {
Expand Down
23 changes: 17 additions & 6 deletions src/main/java/fr/polytech/sim/cycling/BikeSimulator.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,27 @@
import fr.polytech.sim.Simulation;
import fr.polytech.sim.log.FileLogger;
import fr.polytech.sim.log.Logger;
import fr.polytech.sim.log.LoggerFactory;
import fr.polytech.sim.utils.Context;

import java.util.Iterator;

/**
* Bike simulation.
*/
public class BikeSimulator implements Simulation {
private final Logger logger = new FileLogger("BikeSimulator");
public class BikeSimulator implements Simulation {
private final Logger logger = LoggerFactory.getLogger("NomDuLogger");

public void run() {
Bike bike = new SimpleBike();
this.logger.log("Bike's speed %.2f Km/h.", bike.getVelocity());
this.logger.log("Bike's mass %.2f Kg.", bike.getMass());
// On utilise Context.injectAll pour obtenir toutes les instances de Bike
Iterator<Bike> bikes = Context.injectAll(Bike.class);
while (bikes.hasNext()) {
Bike bike = bikes.next();
// Log les information pour chaque Bike
logger.log("Simulating bike: %s ", bike.getClass().getSimpleName());
logger.log("Bike's speed : %.2f km/h.", bike.getVelocity());
logger.log("Bike's mass : %.2f kg.", bike.getMass());
}

}
}
}
28 changes: 28 additions & 0 deletions src/main/java/fr/polytech/sim/cycling/TagAlongBike.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package fr.polytech.sim.cycling;

import fr.polytech.sim.transport.Vehicle;
import fr.polytech.sim.transport.Wheel;

public class TagAlongBike extends Bike {

private Bike parentBike;
private Bike childBike;
private Wheel frontWheel;
private Wheel backWheel ;
public TagAlongBike(Bike parentBike, Bike childBike) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Il a fallu un constructeur sans paramètre pour que l'injection de dépendance marche.

super();
this.parentBike = parentBike;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

C'est un vélo avec

  • Un vélo parental,
  • Un vélo enfant, et
  • Deux roues.
    Ca fait une vélo à 6 roues, et implique une simulation erronée.

this.childBike = childBike;

this.frontWheel = new Wheel(this);
this.backWheel = new Wheel(this);
this.components.add(parentBike);
this.components.add(childBike);
this.components.add(frontWheel);
this.components.add(backWheel);
}
@Override
public double getPush(){

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

À quoi ca sert cette rédifinission ?

return parentBike.getPush();
}
}
6 changes: 3 additions & 3 deletions src/main/java/fr/polytech/sim/log/ConsoleLogger.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ public ConsoleLogger(String name) {

@Override
public void log(String format, Object... args) {
String entry = String.format(format, args);
String message = String.format("%s\t%s\n", this.name, entry);
System.out.print(message);

String message = logMessage(format, args);// construction du message ne utilisant la methode de la classe de base
System.out.print(message);// affichage du message au niveau de la console
}
}
5 changes: 2 additions & 3 deletions src/main/java/fr/polytech/sim/log/FileLogger.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,9 @@ public FileLogger(String name) {

@Override
synchronized public void log(String format, Object... args) {
String entry = String.format(format, args);
String message = String.format("%s\t%s\n", this.name, entry);
String message = logMessage(format,args);// Construction du message en utilisant la méthode de la classe de base
try (FileWriter fileWriter = new FileWriter(FILE_NAME, true)) {
fileWriter.write(message);
fileWriter.write(message); // ecrire le message dans le fichier de logs
} catch (IOException e) {
throw new RuntimeException(e);
}
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/fr/polytech/sim/log/NamedLogger.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,10 @@ protected NamedLogger(String name) {
this.name = name;
}

protected String logMessage(String format, Object...args){

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cette méthode ne respecte pas le patron "methode template" qui exige au moins une méthode abstraite. Voir support des cours pour plus d'info.

//Méthode modèle pour construire le message de log
String entry = String.format(format, args);
return String.format("%s\t%s\n" , this.name, entry);
}

}
5 changes: 5 additions & 0 deletions src/main/java/fr/polytech/sim/transport/PushProvider.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package fr.polytech.sim.transport;

public interface PushProvider {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'inteface pourrait être replacer par la classe abstraite Vehicle.

double getPush();
}
10 changes: 5 additions & 5 deletions src/main/java/fr/polytech/sim/transport/Vehicle.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@

import fr.polytech.sim.log.ConsoleLogger;
import fr.polytech.sim.log.Logger;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import fr.polytech.sim.log.LoggerFactory;

import java.util.*;

/**
* Vehicle abstraction.
*/
public abstract class Vehicle implements MobileObject {

private final Logger logger = new ConsoleLogger("Vehicle");
protected final Set<MobileObject> components = new HashSet<>();

protected final List<MobileObject> components = new ArrayList<>();
private final Logger logger = LoggerFactory.getLogger("NomDuLogger");
/**
* Force applied to push the vehicle.
*
Expand Down
12 changes: 8 additions & 4 deletions src/main/java/fr/polytech/sim/transport/Wheel.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import fr.polytech.sim.cycling.Bike;
import fr.polytech.sim.log.ConsoleLogger;
import fr.polytech.sim.log.Logger;
import fr.polytech.sim.log.LoggerFactory;

import java.util.Objects;

/**
Expand All @@ -12,16 +14,18 @@
public class Wheel implements MobileObject {
private static final double DEFAULT_MASSE = 10;

private final Logger logger = new ConsoleLogger("Wheel");
private final Clock clock = new Clock();
private final Bike drive;
private final Clock clock = Clock.getInstance();// permet de récuperer l'instance lors de la creation du singleton
private final PushProvider drive;
private final Logger logger = LoggerFactory.getLogger("NomDuLogger");



/**
* Constructor.
*
* @param drive the object providing push power.
*/
public Wheel(Bike drive) {
public Wheel(PushProvider drive) {
Objects.requireNonNull(drive, "Bike must not be null.");
this.drive = drive;
}
Expand Down
4 changes: 3 additions & 1 deletion src/main/java/fr/polytech/sim/utils/Context.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ public static <T> T inject(Class<T> klass) {
*/
public static <T> Iterator<T> injectAll(Class<T> klass) {
/* TODO: implement the right logic */
throw new UnsupportedOperationException("Method not implemented");
ServiceLoader<T> loader = ServiceLoader.load(klass);
return loader.iterator();
//throw new UnsupportedOperationException("Method not implemented");
}
}
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
fr.polytech.sim.cycling.SimpleBike
fr.polytech.sim.cycling.TagAlongBike