Laden...

Entwurfsmuster Observer

Erstellt von pro vor 16 Jahren Letzter Beitrag vor 16 Jahren 17.480 Views
P
pro Themenstarter:in
216 Beiträge seit 2006
vor 16 Jahren
Entwurfsmuster Observer

Beschreibung:

Momentan bin ich am Erlernen von grundlegenden Entwurfsmustern. Ich habe nun einige Entwurfsmuster theoretisch kennengelernt. Diese beginne ich nun praktisch zu implementieren. Das Observerpattern war mein erstes Entwurfsmuster, welches ich kurz probierte anhand eines simplen Windowsform Beispiel zu implementieren.

Das Beispiel besteht aus 2 Windows Forms, d.h. einem Subjekt (Subject) und einem Beobachter (Watcher). In diesem Projekt gibt es noch zwei Interface, welche die Benachrichtigungen implementieren (IObserver / IObservable).

Das Subjekt implementiert das IObservable Interface, welches die Registrierung der Beobachter ermöglicht.


public interface IObservable
    {
        void Register(IObserver observer);
        void Unregister(IObserver observer);
    }

Der Beobachter implementiert das IObserver Interface, welches die Benachrichtung dieser beobachter Objekte ermöglicht.


    public interface IObserver
    {
        void Notify(object obj);
    }

Die Verwaltung der Beobachter läuft im Subjekt einfach über eine generische Liste (kann auch anders gelöst werden).


/// <summary>
/// Enthält alle Beobachter
/// </summary>
List<IObserver> watchers = new List<IObserver>();

In der Registrierung von Beobachter im Subjekt, werden lediglich die Beobachter Objekte an die Liste gehängt bzw. beim Unregister von der Liste entfernt.


        /// <summary>
        /// Registriert Beobachter
        /// </summary>
        /// <param name="observer">spez. Beobachter</param>
        public void Register(IObserver observer)
        {
            this.watchers.Add(observer);
            this.counter++;
        }

      /// <summary>
        /// Meldet Beobachter ab
        /// </summary>
        /// <param name="observer">spez. Beobachter</param>
        public void Unregister(IObserver observer)
        {
            this.watchers.Remove(observer);
        }

Die Benachrichtung verläuft dann im Subjekt über eine Foreach Schleife, in welcher das Subjekt bei jedem Beobachter die Notify Methode aufruft.

Im Subjekt sieht der Code wiefolgt aus :


   /// <summary>
        /// Eventhandler für 'Create watcher' Button
        /// </summary>
        /// <param name="sender">Sender</param>
        /// <param name="e">Eventargs</param>
        private void OnStateChange(object sender, EventArgs e)
        {
            int green = ((int)(new Random().Next(255)));
            int red = ((int)(new Random().Next(255)));
            int blue = ((int)(new Random().Next(255)));

            this.BackColor = Color.FromArgb(red, green, blue);

            //Alle Beobachter benachrichtigen
            foreach (IObserver watcher in watchers)
            {
                watcher.Notify(this.BackColor);
            }
        }




Im Beobachter sieht die Benachrichtung so aus :


        #region IObserver Members

        /// <summary>
        /// Benachrichtigungsmethode, wird vom Subjekt bzw. vom Mainform aufgerufen
        /// </summary>
        /// <param name="obj">Benachrichtigungsobjekt</param>
        public void Notify(object obj)
        {
            //Benachrichtigungslogik
            MessageBox.Show("The backgroundcolor was changed",
                "Watcher " + this.Name, MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        #endregion

Ich konnte das Projekt leider nicht hochladen, deshalb habe ich es auf meinem Webserver verlinkt. Falls es evtl. ein Administrator dieses Forum an diesen Thread anhängen könnte, wär ich froh.

Das Beispielprojekt findet ihr im Anhang.

Für Kritik und Feedback bin ich offen.

Vielen Dank für Eure Rückmeldungen.

Entwurfsmuster, Observer, Pattern

49.485 Beiträge seit 2005
vor 16 Jahren

Hallo pro,

in .NET verwendet/implementiert man das Observer-Pattern i.d.R. nicht! Stattdessen verwendet man Events. Siehe [FAQ] Eigenen Event definieren

herbivore

P
pro Themenstarter:in
216 Beiträge seit 2006
vor 16 Jahren

Hallo herbivore,

Da geb ich Dir recht. Performancemässig ist jedoch die Kommunikation über Methoden schneller als über Delegates in CSharp.

Grüsse, pro

49.485 Beiträge seit 2005
vor 16 Jahren

Hallo pro,

ich wollte es ja auch nur gesagt habe. Außerdem ist die minimal schlechte Performance hier nur der Preis für die größere Flexibilität von Events. Außerdem wird es so gut wie keinen Fall geben, in dem sich die minimal schlechte Performance praktisch auswirken wird.

herbivore

P
pro Themenstarter:in
216 Beiträge seit 2006
vor 16 Jahren

Außerdem ist die minimal schlechte Performance hier nur der Preis für die größere Flexibilität von Events.

Ok - das stimmt.

D
368 Beiträge seit 2005
vor 16 Jahren

Hallo,

mir ist nicht wirklich bewusst warum man das Observer Pattern in .Net eher nicht nutzen sollte. Es geht doch beim Observer Pattern darum, gegen Interfaces zu programmieren und jeder der sich registrieren möchte meldet sich beim Observer an und ab. Somit hat der Observer, bei entsprechender Intelligenz doch auch den Überblick über seine Clients. Das fehlt doch aber wenn ich nur mit Events arbeite. Niemand meldet sich beim Observer an sondern jeder bekommt ein Event, ob er sich anmeldet oder nicht. Ist es nicht aus diesem Grund legitim das Observer Pattern, wie oben gepostet, zu nutzen?

Gruß

dragi

0
767 Beiträge seit 2005
vor 16 Jahren

auch die events bekommen nur die, die sich dafür angemeldet haben... anmeldung erfolg hier eben mit += und abmeldung mit -=

loop:
btst #6,$bfe001
bne.s loop
rts

49.485 Beiträge seit 2005
vor 16 Jahren

Hallo dragi,

mir ist nicht wirklich bewusst warum man das Observer Pattern in .Net eher nicht nutzen sollte.

und mir fällt kein Grund ein, warum man es tun wollte ... außer eben, dass man wie pro "am Erlernen von grundlegenden Entwurfsmustern" ist.

Wie 0815Coder schon sagt, kann man bzw. muss man sich bei Events ganz genauso an und abmelden wie beim eigentlichen Observer-Pattern.

Im Prinzip kann man sogar soweit gehen, dass Events und das Observer-Pattern das gleiche sind. Oder anders gesagt: Mit Events steht ein Sprachmittel zur Verfügung, um standardisiert das Observer-Pattern in .NET zu realisieren.

Und diese Standardisierung ist auch genau der Grund, warum man das Observer-Pattern immer über Events realisieren sollte.

herbivore

3.971 Beiträge seit 2006
vor 16 Jahren

Die Idee ist aber nicht schlecht, die da pro verfolgt, sich Gedanken drüber zumachen, wie man das (auch anders) umsetzen kann, allein schon deshalb um das ganze zu verstehen (zu lernen). Es muss ja nicht nur das Observer-Pattern sein, dass man mal theoretisch durchexerzieren sollte / könnte.

Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...

D
368 Beiträge seit 2005
vor 16 Jahren

Der einzige Unterschied zwischen Events und dem Observer pattern ist doch aber, das der Observer alle angemeldeten Clients kennt. Das ist doch bei Events nicht der Fall. Deshlab möchte ich wiedersprechen und behaupten das vom Architektur Gedanken her Events und Observer nicht das gleiche sind!

Gruß

Dragi

3.971 Beiträge seit 2006
vor 16 Jahren

Bei Events kannst du auch einzeln mit Foreach durchgehen und "sehen" wer angemeldet ist.

Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...

D
368 Beiträge seit 2005
vor 16 Jahren

Original von kleines_eichhoernchen
Bei Events kannst du auch einzeln mit Foreach durchgehen und "sehen" wer angemeldet ist.

Oh, dann hab ich nichts gesagt und nehme alles zurück! Dann stimme ich mit der allgemeinen Meinung dieses Threads überein.

Gruß

Dragi

P
pro Themenstarter:in
216 Beiträge seit 2006
vor 16 Jahren

Hallo kleines_eichhoernchen,

Bei Events kannst du auch einzeln mit Foreach durchgehen und "sehen" wer angemeldet ist.

Durch was kann man da loopen? Kannst Du dazu ein Beispiel machen (nur falls du Zeit dazu hast...😉)?

Vielen Dank.

Grüsse, pro

3.971 Beiträge seit 2006
vor 16 Jahren

Auf die schnelle habe ich nur Gewusst wie: Behandeln mehrerer Ereignisse mit Ereigniseigenschaften. Bin mir nicht mehr sicher ob man ein MulticastDelegate auch einzeln mit Foreach durchlaufen kann.

EDIT:


System.MulticastDelegate.GetInvocationList();

Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...

1.985 Beiträge seit 2004
vor 16 Jahren

Hallo zusammen,

am Anfang der Diskussion wurde als Nachteil von Events erwähnt, dass sie, im Vergleich zum Observer-Pattern, eine schlechte Performance haben. Wie groß ist dieser Unterschied denn und wie kommt der zustande?

Gruß,
Fabian

"Eine wirklich gute Idee erkennt man daran, dass ihre Verwirklichung von vornherein ausgeschlossen erscheint." (Albert Einstein)

Gefangen im magischen Viereck zwischen studieren, schreiben, lehren und Ideen umsetzen…

Blog: www.fabiandeitelhoff.de

P
pro Themenstarter:in
216 Beiträge seit 2006
vor 16 Jahren

Hallo,

Auf die schnelle habe ich nur Gewusst wie: Behandeln mehrerer Ereignisse mit Ereigniseigenschaften. Bin mir nicht mehr sicher ob man ein MulticastDelegate auch einzeln mit Foreach durchlaufen kann.

Vielen Dank - ich werde das nachprüfen.

Wie groß ist dieser Unterschied denn und wie kommt der zustande?

Ich habe dies nur im Zusammenhang mit dem Observer Artikel auf Codeproject.com erfahren. Der Artikel dazu findest Du hier : http://www.codeproject.com/dotnet/Observer.asp

Communicating through methods of an interface is faster than using delegates in .NET.

Grüsse, pro

49.485 Beiträge seit 2005
vor 16 Jahren

Hallo Fabian,

Wie groß ist dieser Unterschied denn [...]?

wie ich schon sagte: nicht nennenswert.

herbivore

1.985 Beiträge seit 2004
vor 16 Jahren

Hallo ihr beiden,

danke für den Link und die Antworten.

Gruß,
Fabian

"Eine wirklich gute Idee erkennt man daran, dass ihre Verwirklichung von vornherein ausgeschlossen erscheint." (Albert Einstein)

Gefangen im magischen Viereck zwischen studieren, schreiben, lehren und Ideen umsetzen…

Blog: www.fabiandeitelhoff.de

J
1.114 Beiträge seit 2007
vor 16 Jahren

Der Vollständigkeit halber sei noch erwähnt, dass das Observer Pattern nur deshalb über Events nachgebildet werden kann, weil .NET Multicast Events unterstützt. In anderen Programmiersprachen (z.B. Delphi) geht das dann nicht mehr so und man muss den Weg über Interfaces gehen.

I
1.739 Beiträge seit 2005
vor 16 Jahren

Der Vollständigkeit halber sei noch Erwähnt das Event-Pattern und Observerpattern verschiedene Dinge sind.
Das Eventpattern ist sicher eine praktische Sache kann aber den Observer nicht ersetzen.(Ebenso ersetzt der Observer nicht den MVC.)
Praktisch findet man oft sowieso nie eine reine Patternimplementation, deswegen heissen die Dinger ja auch Pattern und nicht Templates.
Die meisten Observerimplementationen unter .Net leben auch quasi vom Eventpattern(siehe Post von Jelly).
Die schlechte Performance von Events ensteht oft durch Vermeidung des Observerpatterns in Form von "Frickelei". Das war z.B. unter VB6 extrem, da man dort Eventhandler nicht nach Bedarf Ab- und Zuschalten konnte. Unter .Net kann man den Oserver umgehen mit guter Performance, zu Lasten von Lesbarkeit und Trennung des Codes von Aufgaben.

S
8.746 Beiträge seit 2005
vor 16 Jahren
  1. Das Event-Pattern ist nichts weiter als eine Signaturkonvention für den Delegaten (sender, args)
  2. .NET-Events entsprechen der besten Observer-Variante mit maximaler Entkopplung
  3. .NET-Event sparen satte drei Interfaces, produzieren weniger Code und sind besser lesbar

Der einzige vielleicht berechtigte "Einwand" gegen Events ist, dass "compiler-magic" doe OO-Struktur hinter der ganzen Kiste verbirgt. In meinen Augen aber esoterisch.

Die Geschwindigkeitsvorteile direkter Calls, möglicherweise sogar via Inlining, kommen beim Observer-Pattern eh nicht zum Zuge (wg. der Interface-Indirektion). Events dürften daher höchstens 10% Overhead haben (Delegaten-Konstruktor).

Events sind m.E. eine der besten Erfindungen seit geschnitten Brot.

Eine schöne Aussage findet man hier:

http://www.gavaghan.org/blog/2007/07/18/java-and-csharp-language-nuances-make-you-think-differently/

"In short, the level of effort required to make the Observer Pattern work in Java is so overwhelming it is seldom implemented except in the most compelling cases. Most Java developers, though not intentionally lazy, simply don’t think to reach for this tool and end up creating tightly coupled code which is harder to test and maintain."