Abou Chleih

{the magic lies between the brackets}

Menü Schließen

Schlagwort: Java

Observer Pattern (Beobachter-Muster) in Java und C#

Wie benachrichtige ich mehrere Clients möglichst ohne Zeitverlust und ohne das Rad neu zu erfinden?
Eine weitverbreitete Möglichkeit ist das Observer Pattern (und erweitert, das Subscriber Pattern).
Es ist push-basiert, der Beobachtete gibt also allen Beobachtern Bescheid, was eine Benachrichtigung an die Beobachter in kürzester Zeit ermöglicht.

ObserverPattern

Was wir in Java dafür brauchen sind folgende Klassen und Interfaces, welche wir im Code referenzieren. In C# gibt es keine äquivalenten Klassen, wir müssen etwas selber schreiben.
[tabs]
[tab title=“Java“]

import java.util.Observable;
import java.util.Observer;

[/tab]
[/tabs]

Erstellen wir nun die Klasse, welche später beobachtet werden soll.
In C# nutzen wir EventHandler für eine asynchrone Benachrichtigung:

[tabs]
[tab title=“Java“]

public class Beobachteter extends Observable

[/tab]
[tab title=“C#“]

public class Observable
	{
		private bool changed;
		event EventHandler notifier;
		
		public void addObserver(Observer obs)
		{
			notifier += obs.update;
		}
	
		private void notifyObservers(dynamic obj)
		{
			if (this.changed) {
				if(notifier != null)
					 notifier(obj, EventArgs.Empty);
			}
			this.changed = false;
		}
		
		public void setChanged()
		{
			this.changed = true;
		}
		
		public void doIt(){
			setChanged();
			notifyObservers(32123);
		}
		
	}

[/tab]
[/tabs]

Wir lassen unseren Beobachteten die Klasse Observable im Namespace java.util.* erben. (Siehe oben)
Dadurch bekommt die Klasse u.A. folgende Methode vererbt, welche wir im Folgenden nutzen:
[tabs]
[tab title=“Java“]

public void AddObserver(){
       Beobachteter.addObserver(Observer o);
}

[/tab]
[tab title=“C#“]

 Durch die eigene Implementierung, stehen uns die identischen Methoden zur Verfügung. 

[/tab]
[/tabs]

Wie man auf dem Bild sieht, muss man nun die Beobachter (Observer) einem Beobachtbaren (Observable) hinzufügen, im Folgenden nenne ich diesen dann Beobachteten.
Wir erstellen verschiedene Beobachter und fügen diese nun einem Objekt der Klasse Beobachteter zu, welche – der Einfachheit halber – direkt in den Beobachtern erstellt wird.
Die Beobachter implementieren das Interface von java.util.Observer.

[tabs]
[tab title=“Java“]

public class Beobachter implements Observer{
    public Beobachter(){
         Beobachteter observable = new Beobachteter();
         observable.addObserver(this); //fügt dem Beobachteten mich als Beobachter hinzu.
    }
}

[/tab]
[tab title=“C#“]

 	public class Observer
	{
		string name;
		
		public Observer()
		{
		}
		
		public Observer(string name){
			this.name = name;
		}
	
		public void update(object message, EventArgs args){
			//Console.WriteLine(this + "received: "+message+obs);
		}
		
		public override string ToString()
		{
			return "{Observer,"+this.name+"}";
		} 
	}

[/tab]
[/tabs]

Nun haben wir einen oder mehrere Beobachter und einen Beobachteten.
Wie lassen wir die Beobachter nun wissen, wenn sich etwas ändert?
Die Klasse Observable bietet hier einige passende Methoden. Ich fokussiere mich hier allerdings auf folgende zwei:

[tabs]
[tab title=“Java“]

 setChanged(); 
 notifyObservers(message);

[/tab]
[tab title=“C#“]

setChanged();  
notifyObservers(message);

[/tab]
[/tabs]

Durch das dynamic keyword können wir dem EventHandler „notifier“ jegliche Daten als Parameter durchreichen, diese Implementierung vereinfacht das Handling der Daten extrem.

setChanged() ist von Nöten, da ein Beobachter auch nur benachrichtigt wird, wenn sich auch etwas geändert hat.
In Java ist es zudem sehr praktisch, dass man jede Art von Daten in der Methode

notifyObservers();

versenden kann. Mit dieser werden die Beobachter auch benachrichtigt.

Im Java Observer wird nun die Methode

update(Observable _ob, Object message)

, welche wir durch das Interface implementierten, ausgeführt.
In C# rufen der EventHandler die Observer-Methode

 update(dynamic message, EventArgs empty) 

aus.

Im Anhang befindet sich das C# Test Projekt, als .sln Solution:
ObserverPattern

Grundlagen der Programmierung: Static Deklaration

Wann sollte man eine Klasse statisch deklarieren und was ist dieses Static eigentlich?
Behandeln wird einmal den zweiten Punkt und nehmen die Klasse Console.
Die Klasse Console besitzt die statische Methode Write().

 

Diese können wir also im Code aufrufen, ohne explizit eine Instanz der Klasse zu erstellen:

 Console.Write("Hello World");

Diese Deklaration nennt man static, da wir hier nicht explizit auf die Daten einer bestimmten Objektinstanz zugreifen, sondern die Daten immer gleich zurück gegeben werden. Unabhängig vom Zustand des Objektes, also von den Werten, welche einer Variable in dem Objekt gegeben werden.

 Console.Write("Hello World");

wird also immer „Hello World“ zurück geben!

Um eine Ausgabe in der Konsole zu tätigen, brauchen wir kein spezielles Console-Objekt, also nicht sowas:

 
Console c = new Console(); 
c.Write("Hello World"); // FALSCH

Wann benötige ich dann „normale“ Methoden und Variablen?

Das kommt in einem anderen Post ;)

© 2018 Abou Chleih. Alle Rechte vorbehalten.

Thema von Anders Norén.