Menu
Coddy logo textTech

Observer-Pattern

Teil des Abschnitts Objektorientierte Programmierung der Java-Journey von Coddy — Lektion 68 von 87.

Das Observer-Muster ist ein Verhaltensmuster, das eine Eins-zu-viele-Beziehung zwischen Objekten herstellt. Wenn ein Objekt (das Subjekt) seinen Zustand ändert, werden alle seine Abhängigen (die Beobachter) automatisch benachrichtigt und aktualisiert. Stellen Sie es sich wie ein Newsletter-Abonnement vor – Abonnenten erhalten Updates, wann immer neue Inhalte veröffentlicht werden.

Das Muster umfasst zwei Hauptkomponenten: ein Subjekt, das eine Liste von Beobachtern führt und diese über Änderungen benachrichtigt, sowie Beobachter, die eine Update-Methode definieren, um auf Benachrichtigungen zu reagieren:

import java.util.ArrayList;
import java.util.List;

interface Observer {
    void update(String message);
}

class NewsPublisher {
    private List<Observer> subscribers = new ArrayList<>();
    
    public void subscribe(Observer observer) {
        subscribers.add(observer);
    }
    
    public void unsubscribe(Observer observer) {
        subscribers.remove(observer);
    }
    
    public void publish(String news) {
        for (Observer subscriber : subscribers) {
            subscriber.update(news);
        }
    }
}

class EmailSubscriber implements Observer {
    private String email;
    
    public EmailSubscriber(String email) {
        this.email = email;
    }
    
    public void update(String message) {
        System.out.println("Email to " + email + ": " + message);
    }
}

Wenn der Publisher Neuigkeiten veröffentlicht, werden alle Abonnenten automatisch benachrichtigt:

NewsPublisher publisher = new NewsPublisher();
publisher.subscribe(new EmailSubscriber("alice@mail.com"));
publisher.subscribe(new EmailSubscriber("bob@mail.com"));

publisher.publish("Breaking news!");
// Ausgabe:
// E-Mail an alice@mail.com: Breaking news!
// E-Mail an bob@mail.com: Breaking news!

Das Observer-Muster fördert eine lose Kopplung – das Subjekt muss die konkreten Klassen seiner Beobachter nicht kennen, sondern nur, dass sie das Observer-Interface implementieren. Dies macht es einfach, neue Beobachtertypen hinzuzufügen, ohne das Subjekt zu ändern.

challenge icon

Aufgabe

Einfach

Lassen Sie uns ein Aktienkurs-Alarmsystem mit dem Observer Pattern bauen! Sie werden ein System erstellen, bei dem ein Stock Ticker mehrere Investoren benachrichtigt, wann immer sich der Aktienkurs ändert, sodass jeder Investor auf seine eigene Weise auf Preisaktualisierungen reagieren kann.

Sie werden Ihren Code über vier Dateien hinweg organisieren:

  • Observer.java: Definieren Sie das Observer-Interface, das alle Investoren implementieren werden. Es sollte eine einzige Methode update(String stockName, double price) deklarieren, die Observer verwenden, um Benachrichtigungen über Preisänderungen zu erhalten.
  • StockTicker.java: Erstellen Sie die Subject-Klasse, die eine Liste von Observern verwaltet und diese über Preisänderungen benachrichtigt. Ihr StockTicker sollte Folgendes haben:

    Ein privates String-Feld für den Aktiennamen (gesetzt über den Konstruktor).

    Ein privates Double-Feld für den aktuellen Preis (anfänglich 0).

    Eine private Liste zum Speichern der abonnierten Observer.

    Eine subscribe(Observer observer)-Methode, die einen Observer zur Liste hinzufügt.

    Eine unsubscribe(Observer observer)-Methode, die einen Observer aus der Liste entfernt.

    Eine setPrice(double price)-Methode, die den Preis aktualisiert und dann alle Observer benachrichtigt, indem sie deren update-Methode mit dem Aktiennamen und dem neuen Preis aufruft.

  • Investors.java: Erstellen Sie zwei verschiedene Arten von Investoren, die das Observer-Interface implementieren:

    DayTrader - hat ein privates Namensfeld, das über den Konstruktor gesetzt wird. Wenn er aktualisiert wird, gibt er [name] received alert: [stockName] is now $[price] - Making quick trade! aus.

    LongTermInvestor - hat ein privates Namensfeld, das über den Konstruktor gesetzt wird. Wenn er aktualisiert wird, gibt er [name] received alert: [stockName] is now $[price] - Holding steady. aus.

    Formatieren Sie den Preis mit zwei Dezimalstellen.

  • Main.java: Bringen Sie Ihr Observer-System zusammen! Sie erhalten drei Eingaben: den Aktiennamen (String), die erste Preisaktualisierung (double) und die zweite Preisaktualisierung (double).

    Erstellen Sie einen StockTicker mit dem angegebenen Aktiennamen. Erstellen Sie einen DayTrader namens "Alice" und einen LongTermInvestor namens "Bob", und abonnieren Sie beide beim Ticker.

    Setzen Sie den Preis auf den ersten Eingabewert (alle Observer werden benachrichtigt). Melden Sie dann Alice ab. Setzen Sie schließlich den Preis auf den zweiten Eingabewert (diesmal sollte nur Bob benachrichtigt werden).

Sie erhalten drei Eingaben in der Reihenfolge: Aktienname (String), erster Preis (double), zweiter Preis (double).

Diese Herausforderung demonstriert die Stärke des Observer Patterns: Der StockTicker weiß nichts über die spezifischen Investorentypen – er weiß nur, dass sie Observer implementieren. Wenn Sie Alice abmelden, erhält sie keine Aktualisierungen mehr, während Bob weiterhin benachrichtigt wird. Diese lose Kopplung macht es einfach, neue Investorentypen hinzuzufügen, ohne den Ticker zu ändern!

Spickzettel

Das Observer-Muster (Beobachter-Muster) ist ein Verhaltensmuster, das eine Eins-zu-viele-Beziehung zwischen Objekten herstellt. Wenn ein Objekt (das Subjekt) seinen Zustand ändert, werden alle seine Abhängigen (die Beobachter) automatisch benachrichtigt und aktualisiert.

Das Muster umfasst zwei Hauptkomponenten:

  • Subjekt: Verwaltet eine Liste von Beobachtern und benachrichtigt diese über Änderungen
  • Beobachter: Definieren eine Update-Methode, um auf Benachrichtigungen zu reagieren

Grundstruktur:

import java.util.ArrayList;
import java.util.List;

interface Observer {
    void update(String message);
}

class Subject {
    private List<Observer> observers = new ArrayList<>();
    
    public void subscribe(Observer observer) {
        observers.add(observer);
    }
    
    public void unsubscribe(Observer observer) {
        observers.remove(observer);
    }
    
    public void notifyObservers(String message) {
        for (Observer observer : observers) {
            observer.update(message);
        }
    }
}

class ConcreteObserver implements Observer {
    public void update(String message) {
        // Auf Benachrichtigung reagieren
    }
}

Anwendungsbeispiel:

Subject subject = new Subject();
subject.subscribe(new ConcreteObserver());
subject.notifyObservers("State changed!");
// Alle angemeldeten Beobachter erhalten das Update

Das Observer-Muster fördert eine lose Kopplung – das Subjekt muss die konkreten Klassen seiner Beobachter nicht kennen, sondern nur, dass sie das Observer-Interface implementieren. Dies macht es einfach, neue Beobachtertypen hinzuzufügen, ohne das Subjekt zu ändern.

Probier es selbst

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // Eingaben lesen
        String stockName = scanner.nextLine();
        double firstPrice = scanner.nextDouble();
        double secondPrice = scanner.nextDouble();
        
        // TODO: Erstelle einen StockTicker mit dem angegebenen stockName
        
        // TODO: Erstelle einen DayTrader namens "Alice"
        
        // TODO: Erstelle einen LongTermInvestor namens "Bob"
        
        // TODO: Melde sowohl Alice als auch Bob beim Ticker an
        
        // TODO: Setze den Preis auf firstPrice (beide Beobachter werden benachrichtigt)
        
        // TODO: Melde Alice ab
        
        // TODO: Setze den Preis auf secondPrice (nur Bob wird benachrichtigt)
        
        scanner.close();
    }
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung