Design patterns
Observateur
Recherche…
Remarques
Quelle est l'intention?
- Adoptez le principe de la séparation des préoccupations.
- Créez une séparation entre le sujet et l'observateur.
- Permettre à plusieurs observateurs de réagir pour changer un seul sujet.
Quelle est la structure?
- L'objet fournit un moyen de s'inscrire, d'annuler l'enregistrement, de notifier.
- Observer fournit un moyen de mise à jour.
Observateur / Java
Le modèle d'observateur permet aux utilisateurs d'une classe de s'abonner aux événements qui se produisent lorsque cette classe traite des données, etc. et d'être avertis lorsque ces événements se produisent. Dans l'exemple suivant, nous créons une classe de traitement et une classe d'observateurs qui seront notifiées lors du traitement d'une phrase - si elle trouve des mots de plus de 5 lettres.
L'interface LongWordsObserver
définit l'observateur. Implémentez cette interface afin d'inscrire un observateur aux événements.
// an observe that can be registered and receive notifications
public interface LongWordsObserver {
void notify(WordEvent event);
}
La classe WordEvent
est l'événement qui sera envoyé aux classes d'observateur une fois que certains événements se sont produits (dans ce cas, les mots longs ont été trouvés)
// An event class which contains the long word that was found
public class WordEvent {
private String word;
public WordEvent(String word) {
this.word = word;
}
public String getWord() {
return word;
}
}
La classe PhraseProcessor
est la classe qui traite la phrase donnée. Il permet aux observateurs d'être enregistrés en utilisant la méthode addObserver
. Une fois les mots longs trouvés, ces observateurs seront appelés en utilisant une instance de la classe WordEvent
.
import java.util.ArrayList;
import java.util.List;
public class PhraseProcessor {
// the list of observers
private List<LongWordsObserver> observers = new ArrayList<>();
// register an observer
public void addObserver(LongWordsObserver observer) {
observers.add(observer);
}
// inform all the observers that a long word was found
private void informObservers(String word) {
observers.forEach(o -> o.notify(new WordEvent(word)));
}
// the main method - process a phrase and look for long words. If such are found,
// notify all the observers
public void process(String phrase) {
for (String word : phrase.split(" ")) {
if (word.length() > 5) {
informObservers(word);
}
}
}
}
La classe LongWordsExample
montre comment enregistrer des observateurs, appeler la méthode process
et recevoir des alertes lorsque des mots longs ont été trouvés.
import java.util.ArrayList;
import java.util.List;
public class LongWordsExample {
public static void main(String[] args) {
// create a list of words to be filled when long words were found
List<String> longWords = new ArrayList<>();
// create the PhraseProcessor class
PhraseProcessor processor = new PhraseProcessor();
// register an observer and specify what it should do when it receives events,
// namely to append long words in the longwords list
processor.addObserver(event -> longWords.add(event.getWord()));
// call the process method
processor.process("Lorem ipsum dolor sit amet, consectetuer adipiscing elit");
// show the list of long words after the processing is done
System.out.println(String.join(", ", longWords));
// consectetuer, adipiscing
}
}
Observateur utilisant IObservable et IObserver (C #)
IObserver<T>
et IObservable<T>
peuvent être utilisées pour implémenter un motif d'observateur dans .NET
-
IObservable<T>
représente la classe qui envoie les notifications -
IObserver<T>
représente la classe qui les reçoit
public class Stock {
private string Symbol { get; set; }
private decimal Price { get; set; }
}
public class Investor : IObserver<Stock> {
public IDisposable unsubscriber;
public virtual void Subscribe(IObservable<Stock> provider) {
if(provider != null) {
unsubscriber = provider.Subscribe(this);
}
}
public virtual void OnCompleted() {
unsubscriber.Dispose();
}
public virtual void OnError(Exception e) {
}
public virtual void OnNext(Stock stock) {
}
}
public class StockTrader : IObservable<Stock> {
public StockTrader() {
observers = new List<IObserver<Stock>>();
}
private IList<IObserver<Stock>> observers;
public IDisposable Subscribe(IObserver<Stock> observer) {
if(!observers.Contains(observer)) {
observers.Add(observer);
}
return new Unsubscriber(observers, observer);
}
public class Unsubscriber : IDisposable {
private IList<IObserver<Stock>> _observers;
private IObserver<Stock> _observer;
public Unsubscriber(IList<IObserver<Stock>> observers, IObserver<Stock> observer) {
_observers = observers;
_observer = observer;
}
public void Dispose() {
Dispose(true);
}
private bool _disposed = false;
protected virtual void Dispose(bool disposing) {
if(_disposed) {
return;
}
if(disposing) {
if(_observer != null && _observers.Contains(_observer)) {
_observers.Remove(_observer);
}
}
_disposed = true;
}
}
public void Trade(Stock stock) {
foreach(var observer in observers) {
if(stock== null) {
observer.OnError(new ArgumentNullException());
}
observer.OnNext(stock);
}
}
public void End() {
foreach(var observer in observers.ToArray()) {
observer.OnCompleted();
}
observers.Clear();
}
}
Usage
...
var provider = new StockTrader();
var i1 = new Investor();
i1.Subscribe(provider);
var i2 = new Investor();
i2.Subscribe(provider);
provider.Trade(new Stock());
provider.Trade(new Stock());
provider.Trade(null);
provider.End();
...
REF: Modèles et pratiques de conception dans .NET: le modèle Observer