meillo@11: % @file meillo@34: % @brief Ausarbeitung DesignPatterns `Observer' meillo@11: % @author markus schnalke meillo@11: % @since 2007-05-30 meillo@11: meillo@11: meillo@28: \documentclass[a4paper]{scrartcl} meillo@11: meillo@28: \usepackage[utf8]{inputenc} meillo@11: \usepackage{ngerman} meillo@11: \usepackage{graphicx} meillo@33: \usepackage{listings} meillo@11: \usepackage[automark]{scrpage2} meillo@11: meillo@28: \setkomafont{sectioning}{\normalfont\normalcolor\bfseries} meillo@28: \setlength{\parindent}{0em} meillo@28: \setlength{\parskip}{1.0ex plus 1.0ex minus 0.5ex} meillo@28: \pagestyle{scrheadings} meillo@31: \setcounter{tocdepth}{3} meillo@11: meillo@11: \begin{document} meillo@11: meillo@11: meillo@11: meillo@11: meillo@11: meillo@28: %%%% Titlepage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% meillo@28: \begin{titlepage} meillo@28: \title{Observer-Pattern} meillo@28: \author{Markus Schnalke} meillo@34: \date{2007-08-11} meillo@11: meillo@11: meillo@28: \thispagestyle{empty} meillo@11: meillo@11: meillo@28: \begin{flushright} meillo@11: meillo@28: \rule[8cm]{0cm}{0cm} meillo@28: {\Huge Design Pattern\\ \textbf{Observer}} meillo@11: meillo@28: \rule[2cm]{0cm}{0cm} meillo@28: \textsc{Markus Schnalke\\MatNr: 039131} meillo@11: meillo@28: \end{flushright} meillo@11: meillo@11: meillo@11: meillo@28: \rule[7cm]{0cm}{0cm} meillo@11: meillo@28: \textit{Dies ist meine Ausarbeitung zum Design Pattern ``Observer'' im Rahmen der Vorlesung Softwaretechnik im Studiengang Wirtschaftsinformatik an der Hochschule Ulm.} meillo@11: meillo@28: {\tiny Dieses Dokument darf gerne zitiert, kopiert und weitergegeben werden. Ich bitte nur darum meinen Namen und einen Verweis auf meine Website (http://marmaro.de) zu erwähnen --- danke! } meillo@11: meillo@11: meillo@28: \end{titlepage} meillo@11: meillo@11: meillo@11: meillo@28: meillo@28: \tableofcontents meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: %%%% Einleitung %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% meillo@28: \newpage meillo@28: \section{Einleitung} meillo@28: meillo@28: Ich möchte im Folgenden einen Ansatz zum Verstehen von Design Patterns aufzeigen. Dazu nehme ich das Design Pattern ``Observer'', das ich Stück für Stück aus einer Situation der realen Welt herleiten werde. Es geht mir dabei nicht primär darum euch dieses Pattern zu erklären, vielmehr soll das Erfassen des Zusammenhangs zwischen Realität und Design Patterns gefördert werden. meillo@28: meillo@28: Mein Ziel ist es die \textit{Natürlichkeit} von Design Patterns darzustellen --- weil sie dem Vorgehen in der Realität entsprechen! meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: \section{Meine Vorgehensweise} meillo@28: meillo@28: \begin{quote} meillo@28: Design Pattern sind ``Best Practices'' (= Erfolgsrezepte), meist \textbf{nach Vorbildern in der Realität}. meillo@28: \end{quote} meillo@28: meillo@28: Aus diesem Grund möchte ich nun anhand eines Beispiels aus dem täglichen Leben zeigen, dass das Design Pattern \textbf{Observer} ein absolut natürliches Vorgehen ist, das bei ähnlichen Situationen in Programmen deshalb ebenso verwendet werden sollte. Dass ich hier gerade das Pattern \textbf{Observer} verwende, hat keinen besonderen Grund; es kann wohl (fast) jedes Pattern auf diese Weise verständlich und logisch gemacht werden. meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: \newpage meillo@28: \section{Erarbeitung des Patterns} meillo@28: meillo@28: \subsection{Ausgangssituation} meillo@28: Meine Ausgangssituation von der ich mich zu einer möglichst optimalen Lösung vorarbeiten möchte ist Folgende: meillo@28: meillo@11: \begin{itemize} meillo@28: \item Es gibt Personen die Etwas verkaufen möchten meillo@28: \item Es gibt Personen die Etwas kaufen möchten meillo@11: \item Sie wollen/sollen sich nicht kennen meillo@11: \end{itemize} meillo@11: meillo@28: Gesucht ist natürlich ein möglichst effektives Vorgehen. Eben das ist der Grund, weshalb wir Patterns verwenden möchten: Wir suchen eine effektive Standardlösung für regelmäßig auftretende Problemstellungen. meillo@28: meillo@11: meillo@11: meillo@11: meillo@28: \subsection{Mögliche Ansätze} meillo@28: meillo@28: Um systematisch vorzugehen, überlegen wir uns zunächst, welche primitiven Lösungen für unser Problem in Frage kommen. Dies wären zum Beispiel: meillo@11: \begin{itemize} meillo@11: \item Personen direkt ansprechen meillo@11: \item Laut in die Menge rufen meillo@11: \item Den Freunden erzählen, die es dann weitererzählen meillo@11: \end{itemize} meillo@11: meillo@28: Vermutlich wäre der Eine oder Andere (unbewusst) gleich höher eingestiegen, dennoch zeigen auch (oder gerade) diese simplen Vorgehensweisen Probleme auf, die sonst kaum explizit wahrgenommen werden. meillo@28: meillo@28: Dies sind unter anderem: meillo@28: meillo@11: \begin{itemize} meillo@11: \item Man weiß nicht wer Interesse hat meillo@11: \item nicht mal wieviele meillo@11: \item Manche Interessenten sind vielleicht nur zu bestimmten Zeiten da meillo@28: \item (... oder sie sind taub) meillo@11: \end{itemize} meillo@11: meillo@28: meillo@11: meillo@11: meillo@11: meillo@11: \subsection{Erarbeitung einer Lösung} meillo@11: meillo@29: Im Folgenden möchte ich nun eine Lösung Schritt für Schritt erarbeiten und verbessern, bis sie das unsere Situation auf eine gute Weise löst. meillo@29: meillo@29: Meine Lösung, die ich nun präsentieren möchte, ist eine Pinnwand. Pinnwände werden in der Realität normalerweise verwendet um derartige Problem zu lösen --- kein Wunder, wie wir gleich sehen werden. Die Pinnwand bietet von sich aus schon eine gute Lösung für unsere Problemsituation. meillo@29: meillo@29: meillo@28: \subsubsection{Eine (gute) Lösung: Pinnwand} meillo@11: meillo@29: Die Funktionen die eine Pinnwand anbietet sind: meillo@28: meillo@11: \begin{itemize} meillo@11: \item Man kann Zettel anpinnen meillo@11: \item Hingehen und nach neuen Zetteln schauen meillo@11: \item Zettel lesen meillo@11: \item Zettel abnehmen meillo@11: \end{itemize} meillo@11: meillo@29: Nun sind zwar einige unserer Probleme (wie z.B. dass sich die Personen nicht kennen müssen) gelöst, doch es gibt auch welche die weiterhin bestehen. Dies sind vor allem: meillo@11: meillo@11: \begin{itemize} meillo@11: \item Man muss hingehen, nur um festzustellen, dass nichts Neues dabei ist meillo@11: \item Man kann wichtige Zettel verpassen meillo@11: \item Zettel sollten nicht weggenommen werden können meillo@11: \end{itemize} meillo@11: meillo@29: Diese Unzulänglichkeiten der jetzigen Lösung gilt es nun Schritt für Schritt zu eliminieren. meillo@11: meillo@11: meillo@28: \subsubsection{Verbesserung: Pinnwand-Sekretärin} meillo@11: meillo@29: Mit diesem Semester wurden bei uns Studiengebühren eingeführt. Die häufigen Diskussionen deswegen waren es wohl, die mich auf die Idee gebracht haben, das Geld doch sinnvoll(er) zu investieren. Und so erweitern wir unsere Pinnwand um eine Sekretärin die die Pinnwand verwaltet \dots natürlich mit Studiengebühren finanziert ;-) meillo@29: meillo@29: Nachfolgend möchten wir die Sekretärin und die Pinnwand als Einheit betrachten. Die neuen Features dieser Pinnwand-Sekretärin-Einheit sind folgende: meillo@29: meillo@11: \begin{itemize} meillo@11: \item Man kann bei ihr einen Zettel in Auftrag geben (auch telefonisch) meillo@11: \item (Sie schreibt mit lesbarer Schrift) meillo@11: \item Sie verhindert, dass Zettel abgenommen werden meillo@11: \end{itemize} meillo@11: meillo@29: \dots und wir sind der optimalen Lösung unserer Problemsituation wieder einen Schritt näher. Jedoch nur einen Schritt, denn nicht alle Probleme sind gelöst. meillo@29: Bestehen bleibt, dass man immer noch oft unnötig zur Pinnwand läuft. meillo@28: meillo@11: meillo@11: meillo@11: meillo@28: \subsubsection{2. Verbesserung: Pinnwand-Sekretärin mit Benachrichtigung} meillo@11: meillo@29: Die Studiengebühren sollen uns an dieser Stelle noch nicht ausgedient haben ---immerhin sind es 500 Euro--- und so ist noch genug übrig um userer Sekretärin verlängerte Arbeitszeiten finanzieren zu können. In dieser zusätzlichen Zeit kann sie nun natürlich weitere Aufgaben übernehmen. Dies sind: meillo@29: meillo@11: \begin{itemize} meillo@11: \item Man kann sich bei der Sekretärin nun als ``Interessierter'' registrieren meillo@11: \item Die Sekretärin trägt die Telefonnummer in eine Liste ein meillo@28: \item Zukünftig ruft sie alle Personen der Liste an, wenn sie einen neuen Zettel anpinnt meillo@11: \end{itemize} meillo@28: meillo@11: meillo@11: meillo@11: meillo@28: \subsection{Zusammenfassung des Beispiels} meillo@11: meillo@30: Wir haben nun eine Lösung die die meisten Probleme unserer Situation löst. Ich möchte hier die Funktionsweise nochmals aufzählen: meillo@30: meillo@30: \begin{itemize} meillo@30: \item Man kann neue Zettel anpinnen lassen meillo@30: \item Man kann sich als Interessierter anmelden (und auch abmelden) meillo@30: \item Interessierte werden bei Änderungen der Pinnwand benachrichtigt meillo@30: \item Sie können dann zur Pinnwand gehen und sie sich anschauen meillo@30: \end{itemize} meillo@11: meillo@28: meillo@30: Sind jetzt alle Anforderungen abgedeckt? Ist die geschaffene Struktur zufriedenstellend? Welche Wünsche sind noch offen? Was fehlt? meillo@11: meillo@30: Es gibt natürlich weitere Anforderungen/Wünsche die über das jetzige Modell hinausgehen. Auf einige der verbreitendsten Erweiterungen des Observer-Modells werde ich weiter unten noch eingehen. meillo@30: meillo@11: meillo@11: meillo@11: meillo@11: meillo@11: meillo@11: meillo@11: meillo@11: meillo@11: meillo@11: meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: \newpage meillo@28: \section{Das Pattern} meillo@28: meillo@30: Nun haben wir uns eine Lösung für unser Problem erarbeitet und der nächste Schritt ist es ein allgemein gültiges Lösungsmodell zu erstellen. Ein solches Modell wird ``Pattern'' genannt. meillo@30: meillo@28: meillo@28: \subsection{Überleitung} meillo@30: meillo@30: Um unsere Lösung in das Pattern zu überführen bedarf es ein paar anderer Bezeichnungen: meillo@28: meillo@30: \begin{itemize} meillo@30: \item Pinnwand-Sekretärin-Einheit $\rightarrow$ ``Subject'' meillo@30: \item Die Zettel auf der Pinnwand $\rightarrow$ ``subjectState'' meillo@30: \item Interessenten $\rightarrow$ ``Observers'' meillo@30: \end{itemize} meillo@11: meillo@11: meillo@30: Beim Programmieren sind besonders Interfaces (also Schnittstellen) wichtig. Diese entsprechen den Fähigkeiten die Pinnwand/Sekretärin und Interessenten haben oder anbieten. Dies wären zum Beispiel, dass Interessenten nicht taub sein dürfen, lesen und zur Pinnwand hingehen können müssen. Oder auch die leserliche Schrift der Sekretärin. (Siehe dazu auch die Erarbeitung der Pinnwand-Sekretärin.) meillo@28: meillo@11: meillo@11: meillo@11: meillo@28: \subsection{UML-Diagramme} meillo@30: meillo@30: Um das Pattern darzustellen bieten sich UML-Diagramme an. meillo@30: meillo@28: meillo@28: \begin{figure}[hbt] meillo@28: \centering meillo@31: \includegraphics[width=8cm]{pics/observer_big.png} meillo@28: \caption{Struktur-Diagramm des Observers} meillo@28: \end{figure} meillo@28: meillo@28: meillo@28: meillo@28: \begin{figure}[hbt] meillo@28: \centering meillo@31: \includegraphics[width=8cm]{pics/observer-interaction_big.png} meillo@28: \caption{Interaktions-Diagramm des Observers} meillo@28: \end{figure} meillo@28: meillo@28: meillo@30: Wer den ersten Teil der Ausarbeitung verstanden hat und UML kann, sollte hier keine Probleme haben die Diagramme zu verstehen --- es ist quasi das Gleiche, nur in einer anderen Darstellungsform. meillo@30: meillo@30: meillo@11: meillo@11: meillo@28: \subsubsection{Klassifizierung nach GoF} meillo@11: meillo@30: Die ``Gang of Four'' (sie formulierten die ersten Design-Patterns für die Informatik) habe ein einheitliches Schema zu ihrer Klassifizierung erstellt. Anhand diesem ist der Observer folgendermaßen einzuordnen: meillo@30: meillo@36: \paragraph{Klassifizierung:} meillo@11: Verhaltensmuster, objektbasierend meillo@11: meillo@36: meillo@36: \paragraph{Auch bekannt als:} meillo@11: Publish-Subscribe, Dependents meillo@11: meillo@36: meillo@36: \paragraph{Zweck:} meillo@32: Abhängigkeiten zwischen Objekten erstellen, sodass sich abhängige Objekte ändern, wenn sich das Objekt selbst ändert. meillo@11: meillo@36: meillo@36: \paragraph{Kurzbeschreibung:} meillo@32: Schnittstellen anlegen, damit Abhängigkeiten zwischen Objekten registriert meillo@11: werden können, und um die abhängigen Objekte über Zustandsänderungen zu meillo@11: informieren. meillo@28: meillo@11: meillo@11: meillo@11: meillo@28: meillo@28: \subsection{Beispiele für den Observer in der Praxis} meillo@11: meillo@30: Wo ist das Observer-Pattern nun im täglichen Leben anzutreffen? Natürlich ist hier das Leben in der digitalen Welt gemeint, schließlich geht es uns ja um ein Design-Pattern für die Programmierung. meillo@11: meillo@30: Zuerst einmal ist anzuführen, dass der Observer ein sehr verbreitetes Design-Pattern ist, das recht häufig bei passenden Problemstellungen eingesetzt wird. meillo@30: meillo@30: Primär wäre das alles was mit Model-View-Controller (kurz: MVC) zusammenhängt. MVC wird vor allem für grafische Oberflächen eingesetzt. Dabei fungiert das Model als Subject und die View als Observer. Der Controller ist eher von untergeordneter Bedeutung. (MVC ist übrigens ein Architektur-Pattern.) meillo@30: meillo@30: Aber auch Mailinglisten und Such-Abos (wie bei Ebay) sind optimalerweise nach dem Observer-Pattern implementiert. meillo@30: meillo@30: meillo@30: \textbf{Kein} Beispiel für das Observer-Pattern ist aber der Weblog mit RSS-Feed! Denn hier findet kein Abonnement-Vorgang statt, der Client (Observer) meldet sich nicht bei der Website (Subject) an, und bekommt auch keine Änderungsinformationen zugeschickt. Stattdessen ruft der Client nur Informationen ab, die die Website ständig zur Verfügung stellt. (vgl. Pinnwand ohne Sekretärin) meillo@30: meillo@11: meillo@11: meillo@11: meillo@11: meillo@11: meillo@11: meillo@31: meillo@31: \subsection{Erweiterungen des Patterns} meillo@11: meillo@31: \subsubsection{Ein Observer und mehrere Subjects} meillo@31: Oft ist es nicht nur ein einziges Subject, das beobachtet werden soll. Damit ein Observer mehrere Subjects beobachten kann, muss er den Namen des Subjects mitsenden. So kann festgestellt werden welches Subject betroffen ist. meillo@28: meillo@11: meillo@31: \subsubsection{Nur für bestimmte Informationen anmelden} meillo@36: Eine weitere kleine Erweiterung ist die Anmeldung am Subject für nur bestimmte Informationen. Dies ist sicher auch eine Ergänzung die unsere Pinnwand verbessert hätte. So wäre es dann möglich gewesen sich nur für Zimmerangebote oder ähnliches anzumelden. Auf diese Weise werden auch die unnötigen Updates verringert, was sich positiv auf die Performance auswirken kann. meillo@28: meillo@28: meillo@32: \subsubsection{ChangeManager} meillo@36: Bei komplexen Update-Zusammenhängen ist es empfehlenswert einen ChangeManager zwischen die verschiedenen Subjects und Observers zu stellen. Dieser vermittelt dann unter den Beteiligten und koordiniert die Update-Vorgänge. Der ChangeManager ist eine Instanz vom Mediator-Pattern und üblicherweise Singleton, da normalerweise nur ein ChangeManager für alle Observer-Beziehungen verwendet wird. meillo@28: meillo@28: meillo@31: \subsubsection{Wer ruft notify() auf?} meillo@36: Dies kommt stark auf das Programm an. Beide Alternativen haben ihre Vor- und Nachteile. meillo@28: meillo@36: \paragraph{Das Subject:} meillo@34: Auf diese Weise wird notify() sicher bei jedem setState() aufgerufen, jedoch können die Update-Kosten bei vielen Änderungen in kurzer Zeit sehr hoch werden. meillo@28: meillo@28: meillo@36: \paragraph{Der Observer:} meillo@34: Hier darf nun der Observer den Aufruf von notify() nicht vergessen, dieser kann jedoch zu einem günstigen Zeitpunkt erfolgen, was sich bei Änderungen en-block positiv auswirkt. meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: meillo@28: \newpage meillo@33: meillo@11: \section{Zusammenfassung} meillo@33: meillo@36: Ich habe in meiner Ausarbeitung bisher ganz bewusst auf Quellcode verzichtet, denn ich wollte Design Patterns einmal von der anderen Seite her erklären. Ich wollte vermitteln weshalb das Observer-Pattern so aufgebaut ist wie es ist. Ich wollte Verständnis für Design Patterns entwickeln und zeigen, dass sie absolut logische Lösungen sind. meillo@33: meillo@33: \paragraph{In drei Sätzen:} meillo@28: \begin{itemize} meillo@28: \item Menschen denken basierend auf der Realität meillo@36: \item deshalb Design Patterns auf die Realität zurückführen meillo@28: \item Patterns anwenden weil man es in der Realität auch so machen würde meillo@28: \end{itemize} meillo@11: meillo@11: meillo@34: Design Patterns sind dabei Modelle wie Quellcode aufgebaut werden sollte. Sie sind kein Code --- sie beschreiben nur wie Code sein sollte. Das ist auch ganz gut so, denn: meillo@34: meillo@34: \begin{quote} meillo@34: \textbf{Implementierungen sind Schall und Rauch,\\ meillo@34: Konzepte dagegen bleiben bestehen! } meillo@34: \end{quote} meillo@34: meillo@34: Design Patterns sind Konzepte --- Programmiersprachen kommen und gehen, Design Patterns überleben. Wenn man also in die Zukunft investieren möchte, dann sollte man sich Design Patterns aneignen, denn diese Investition ist risikofrei und zudem hoch rentabel! meillo@34: meillo@34: \vspace{10ex} meillo@34: meillo@35: \textit{Ich wollte euch die Natürlichkeit von Patterns nahebringen und euch dafür begeistern.\\ Ich hoffe das ist mir gelungen :-) } meillo@34: meillo@34: \begin{flushright} meillo@34: markus schnalke meillo@34: \end{flushright} meillo@34: meillo@34: meillo@34: meillo@34: meillo@11: meillo@11: meillo@11: meillo@33: \appendix meillo@11: meillo@33: \newpage meillo@11: meillo@33: \section{Beispiel-Implementierung} meillo@11: meillo@34: Ich möchte mich mit Quelltext auf dieses Beispiel im Anhang beschränken. Dennoch finde ich es wichtig, zumindest eine Beispiel-Implementierung vorzeigen zu können, da Quellcode sehr aussagekräftig sein kann. In jeden Fall wird er meine sonstigen Ausführungen gut abrunden. Hier also eine Realisierung in Java: meillo@34: meillo@34: \vspace{4ex} meillo@34: meillo@33: {\scriptsize meillo@33: \lstinputlisting[language=java]{code/observer-example.java} meillo@33: } meillo@34: \begin{flushright} meillo@34: {\tiny Quellcode von http://java2s.com} meillo@34: \end{flushright} meillo@33: meillo@33: meillo@33: meillo@33: meillo@33: meillo@33: meillo@33: \section{Verwendete Software} meillo@11: \begin{itemize} meillo@11: \item Debian GNU/Linux meillo@32: \item \texttt{pdflatex} meillo@11: \item Vim meillo@11: \item qiv und ImageMagick meillo@11: \item Mercurial meillo@11: \end{itemize} meillo@11: meillo@11: meillo@11: meillo@11: meillo@11: meillo@11: meillo@11: \end{document}