You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Kotlin_Enonces/TP1 pour aller plus loin.md

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 du ConsolePrinter;
  • La classe NumberAccumulator, dès qu'elle sera notifiée de la réception d'une donnée, ajoutera cette donnée à son accumulatedValue 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 les secondsToWait 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 et upperBound. 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 tableaux firstNames et lastNames.

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)
}