4.1 KiB
Le but de cet exercice est d'implémenter un petit système de notifications simple, dans lequel un Notifier
peut prévenir d'autres objets, les Receiver
, qu'un événement intéressant s'est produit. Les seuls notifiers que nous créerons sont des générateurs d'objets qui notifient leurs receivers dès qu'un nouvel objet a été créé. Ces différents éléments sont architecturés comme décrit dans le diagramme suivant :
@startuml
skinparam classAttributeIconSize 0
skinparam monochrome true
skinparam shadowing false
skinparam linetype ortho
skinparam class {
BackgroundColor transparent
}
skinparam note {
BackgroundColor transparent
}
hide circle
abstract class Notifier {
+notifyAllReceivers(data : Any)
+addReceiver(rec : Receiver) {exceptions = FullException}
+removeLastReceiver(rec : Receiver)
}
interface Receiver {
+receive(data : Any)
}
abstract class Generator {
-millisecToWait : Int
-continueGeneration : Boolean
-thread : Thread
+Generator(secondsToWait : Float)
+startGenerate()
+stopGenerate()
+{abstract}generate() : Any
}
class FullException extends Exception { }
class FloatGenerator {
+FloatGenerator()
+FloatGenerator(secondsToWait : Float, upperBound : Float)
+generate() : Float
}
class Person {
-firstName : String
-lastName : String
+Person(firstName : String, lastName : String)
+getFirstName() : String
+getLastName() : String
}
class PersonGenerator {
-{static}lastNames : String[] = {"Dupont", "Schmidt", "Clavore"}
-{static}firstNames : String[] = {"Jean", "Paul", "Marie"}
+PersonGenerator(secondsToWait : Float)
+generate() : Person
}
class ConsolePrinter {
-id : String
+ConsolePrinter(id : String)
+receive(data : Any)
}
class NumberAccumulator {
-accumulatedValue : Double
+receive(data : Any)
+getAccumulatedValue() : Double
}
Notifier ---> "0..3\n-receivers" Receiver
Notifier <|-- Generator
Generator <|-- FloatGenerator
Generator <|-- PersonGenerator
PersonGenerator ..> Person
Receiver <|.. ConsolePrinter
Receiver <|.. NumberAccumulator
@enduml
Il vous est demandé de coder cette conception en Kotlin.
Attention, le but n'est pas d'aller le plus rapidement possible, mais de prendre le temps d'explorer les possibilités du langage pour essayer d'être concis et d'adopter le Kotlin spirit.
Les noms des méthodes sont explicites, vous devez être capable de déterminer quoi code. Voici juste quelques informations supplémentaires qui pourront vous aider :
- Les receivers seront stockés dans un simple tableau;
- La méthode
addReceiver(…)
lèvera une exception lorsque le tableau des receivers sera plein; - La classe
ConsolePrinter
, dès qu'elle sera notifiée de la réception d'une donnée, affichera cette donnée sur la sortie standard, préfixée par «id:» où id est évidemment l'id
duConsolePrinter
; - La classe
NumberAccumulator
, dès qu'elle sera notifiée de la réception d'une donnée, ajoutera cette donnée à sonaccumulatedValue
si cette dernière est un nombre (peu importe son type réel); - La classe
Generator
doit permet de générer un objet (grâce àgenerate(…)
) toutes lessecondsToWait
secondes. Chaque générateur possèdera son thread pour effectuer cette génération. - La classe
FloatGenerator
générera un flottant compris entre 0 etupperBound
. Sans informations explicites, cette génération se fera toutes les secondes et la borne supérieure sera 1000. - La classe
PersonGenerator
génèrera des personnes dont la combinaison «Prénom Nom» est choisie aléatoirement parmi les tableauxfirstNames
etlastNames
.
Le programme suivant devra compiler :
fun main() {
val personGen = PersonGenerator(0.8f)
val numGen = FloatGenerator(0.2f, 91827364.5f)
val acc = NumberAccumulator()
personGen.addReceiver(::println)
personGen.addReceiver(acc)
numGen.addReceiver(::println)
numGen.addReceiver(acc)
personGen.startGenerate()
numGen.startGenerate()
Thread.sleep(5000)
personGen.stopGenerate()
numGen.stopGenerate()
println(acc.accumulatedValue)
}