# Ebullition Une application Java et JavaFX pour gérer des capteurs de température. ## Conception ### Interfaces partagées ```mermaid classDiagram class Tickable { +tick()* } <> Tickable class Nameable { +getName()* String +getDisplayName() String } <> Nameable class Identifiable { +getId()* int +setName(name : String)* } <> Identifiable class ObservableIdentifiable { +idProperty()* ReadOnlyIntProperty +getId() int +nameProperty()* StringProperty +getName() String +setName(name : String) +displayNameExpression() StringExpression +getDisplayName() String } <> ObservableIdentifiable class SensorFactory { +create(registry : SensorRegistry, name : String)* Sensor } <> SensorFactory class AutoUpdateStrategyFactory { +create()* AutoUpdateStrategy } <> AutoUpdateStrategyFactory Nameable <|-- Identifiable Identifiable <|-- ObservableIdentifiable Nameable <|-- SensorFactory Nameable <|-- AutoUpdateStrategyFactory ``` L'interface `Tickable` définit une méthode `tick` qui est appelée périodiquement par un thread. Tous les objets héritent en Java de `java.lang.Object` et ont donc une méthode `toString` utilisée principalement pour déboguer. Lorsqu'un objet est fait pour être affiché à l'utilisateur, ce n'est pas du débogage. L'interface `Nameable` définit les méthodes `getName` et `getDisplayName` qui retourne les noms à afficher pour ces objets. Un objet peut être identifié par un identifiant unique, un `UUID` ou un `int`. L'interface `Identifiable` définit la méthode `getId` qui permet de récupérer cet identifiant sous forme d'entier. Elle définit aussi une méthode `setName` pour changer le nom de l'objet. Des objets qui implémentent `Nameable` ou `Identifiable` ne sont pas nécessairement observables. C'est pourquoi l'interface `ObservableIdentifiable` hérite de ces deux interfaces et expose les propriétés observables pour l'identifiant et le nom. Il s'agit du même nom que les méthodes `getId` et `getName` mais en exposant une propriété observable. D'autres éléments de l'application sont nommables, comme certaines fabriques d'objets : `SensorFactory` crée des capteurs et `AutoUpdateStrategyFactory` crée des stratégies d'actualisation automatique. Ces deux interfaces héritent de `Nameable` pour proposer un affichage de ces fabriques dans l'application. ### Capteurs ```mermaid classDiagram class ObservableIdentifiable { ... } <> ObservableIdentifiable class Tickable { +tick()* } <> Tickable class Sensor { -id : IntegerProperty -name : StringProperty -displayName : StringExpression -temperature : DoubleProperty +Sensor(id : int, name : String) +idProperty() int +nameProperty() StringProperty +displayNameExpression() StringExpression +temperatureProperty() ReadOnlyDoubleProperty +getTemperature() double } class ManualSensor { +temperatureProperty() DoubleProperty } class AutoSensor { -updateStrategy : ObjectProperty~AutoUpdateStrategy~ +tick() +getUpdateStrategy() AutoUpdateStrategy +setUpdateStrategy(s : AutoUpdateStrategy) +updateStrategyProperty() ReadOnlyObjectProperty~AutoUpdateStrategy~ } class VirtualSensor { -sources : ObservableList~DataSource~ -sourcesProperty : ListProperty~DataSource~ +addSource(s : Sensor, weight : double) +removeSource(s : Sensor) bool +sourcesProperty() ReadOnlyListProperty~DataSource~ #compute() } class DataSource { -sensor : Sensor -weight : DoubleProperty +sensor() Sensor +weight() double } Sensor <|-- ManualSensor Sensor <|-- AutoSensor Sensor <|-- VirtualSensor ObservableIdentifiable <|.. Sensor Tickable <|.. AutoSensor DataSource "*" <-- VirtualSensor Sensor "1" <-- DataSource ``` Un capteur est un objet observable et identifiable. S'il peut être mis à jour périodiquement comme c'est le cas pour les capteurs automatiques `AutoSensor`, il implémente l'interface `Tickable`. Un capteur manuel ne fait qu'autoriser publiquement la modification de la température par rapport à la classe abstraite `Sensor`. Un capteur virtuel est composé de plusieurs sources de température. C'est une variante du patron de conception composite : chaque capteur virtuel contient une liste de capteurs et de poids associés avec des objets `DataSource`.