Compléter la classe abstraite Observable de manière à pouvoir disposer du mécanisme Observateur/Observable.
Compléter la classe abstraite Observable de manière à pouvoir disposer du mécanisme Observateur/Observable.
Vérifiez la validité de votre implémentation à l'aide des tests fournis.
Vérifiez la validité de votre implémentation à l'aide des tests fournis.
Lors du dernier test, une *ConcurrentModificationException* surviendra peut-être selon votre implémentation.
En effet, si l'observateur se désabonne pendant la boucle de notification, le risque de est modifier la structure sur laquelle on itère.
Pour remédier à ce problème, deux pistes s'offrent à vous :
-[trouver une autre collection](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Collection.html) qui ne posera pas cet inconvénient
- modifier le code d'Observable pour y pallier.
```java
```java
packagefr.univlille.iut.r304.tp3.q1;
packagefr.univlille.iut.r304.tp3.q1;
...
@@ -62,35 +68,36 @@ classDiagram
...
@@ -62,35 +68,36 @@ classDiagram
class Texte
class Texte
Texte : +Texte(InputStream)
Texte : +Texte(InputStream)
Texte : +startReading() void
Texte : +commencer() void
Texte --> "1" Scanner : #scan
Texte --> "1" Scanner : #scan
```
```
ainsi que d'une classe Analyseur, chargée d'afficher au fur et à mesure la progression sur l'objectif donné, ici simplement en terme de lignes à saisir :
ainsi que d'une classe Objectif, chargée d'afficher au fur et à mesure la progression sur l'objectif donné, ici simplement en terme de lignes à saisir :
```mermaid
```mermaid
classDiagram
classDiagram
class Analyseur{
class Objectif {
-objectif : int
-nbRestant : int
}
}
Analyseur : +do() void
Objectif : +do() void
Objectif : +isDone() boolean
```
```
On devra par exemple pouvoir dérouler le scénario suivant (pour y parvenir quelques questions ci-dessous pour vous guider) :
On devra par exemple pouvoir dérouler le scénario suivant (pour y parvenir quelques questions ci-dessous pour vous guider) :
<pre>
```
>>>Objectif 1 - nombre de lignes : encore 3<<<
nombre de lignes : encore 3
<b>Hello</b>
Hello
>>>Objectif 1 - nombre de lignes : encore 2<<<
nombre de lignes : encore 2
<b>The answer is 42</b>
The answer is 42
>>>Objectif 1 - nombre de lignes : encore 1<<<
nombre de lignes : encore 1
<b>Sayonara</b>
Sayonara
>>>Objectif 1 - nombre de lignes atteint<<<
nombre de lignes atteint
<b>Mission accomplie</b>
Ah ?
<b>!fin</b>
C'est déjà fini
Fin de la saisie.
```
</pre>
*En gras, les saisies utilisateurs, les autres chaînes sont affichées par le programme*
* Qu'est-ce qui est observable ici ? \
* Qu'est-ce qui est observable ici ? \
Faîtes hériter d' *Observable* la classe correspondante.
Faîtes hériter d' *Observable* la classe correspondante.
...
@@ -100,27 +107,40 @@ Faîtes implémenter *Observer* à la classe correpsondante.
...
@@ -100,27 +107,40 @@ Faîtes implémenter *Observer* à la classe correpsondante.
Faîtes en sorte qu'elle soit bien envoyée par l'observable.
Faîtes en sorte qu'elle soit bien envoyée par l'observable.
* Dans un *Main*, instancier les différentes classes nécessaires à obtenir le scénario ci-dessus en pensant bien à gérer l'abonnement et le désabonnement de l'observateur à l'observable.
* Dans un *Main*, instancier les différentes classes nécessaires à obtenir le scénario ci-dessus en pensant bien à gérer l'abonnement et le désabonnement de l'observateur à l'observable.
### Autres analyseurs
Écrivez des tests qui démontrent le bon fonctionnement de votre implémentation.
On va désormais ajouter d'autres analyseurs, sur les mêmes saisies, mais vérifiant un critère plus fin, qu'un caractère ait été saisi un certain nombre de fois.
Pour ce faire, on va bien sûr éviter d'aller lire sur l'entrée standard...
À la place, on pourra donner un flux d'entrée vers une chaîne de caractères, par exemple
On va désormais ajouter d'autres objectifs, sur les mêmes saisies, mais vérifiant un critère plus fin, qu'un caractère ait été saisi un certain nombre de fois.
Créer une classe pour ce faire, de manière à mutualiser le plus possible le code avec **Analyseur**.
Créer une classe pour ce faire, de manière à mutualiser le plus possible le code avec **Analyseur**.
Là encore, vous réaliserez des tests.
```
<pre>
nombre de lignes : encore 3
>>>Objectif 1 - nombre de lignes : encore 3<<<
nombre de a : encore 5
nombre de a : encore 5
Hello
<b>Hello</b>
nombre de lignes : encore 2
>>>Objectif 1 - nombre de lignes : encore 2<<<
nombre de e : encore 4
>>>Objectif 2 - nombre de e : encore 4<<<
The answer is 42
<b>The answer is 42</b>
nombre de lignes : encore 1
>>>Objectif 1 - nombre de lignes : encore 1<<<
nombre de e : encore 2
>>>Objectif 2 - nombre de e : encore 2<<<
Sayonara
<b>Sayonara</b>
nombre de lignes atteint
>>>Objectif 1 - nombre de lignes atteint<<<
nombre de e : encore 2
>>>Objectif 2 - nombre de e : encore 2<<<
The end
<b>The end</b>
nombre de e atteint
>>>Objectif 2 - nombre de e atteint<<<
Rideau
<b>Rideau</b>
```
<b>!fin</b>
Fin de la saisie.
</pre>
Construisez 1 ou 2 autres objectifs sur d'autres critères, par exemple avec un nombre de mots d'une taille donnée ou un nombre de majuscules ou chiffres à atteindre.
Quels sont les avantages de reposer sur le patron Observer/Observable ?