===== OO-Basics ===== * Abstraction * Encapsulation * Polymorphism * Inheritance ===== OO-Patterns ===== ==== Strategy ==== Definiert eine Familie von Algorithmen, kapselt sie einzeln und macht sie austauschbar. Das Stratgegy-Muster ermöglicht es, den Algorithmus unabhängig von den Clients variieren zu lassen, die ihn einsetzen. Punkt für Punkt: * Sie werden nicht allein dadurch zu einem guten OO-Designer, dass Sie die OO-Basics beherrschen. * Gute OO-Entwürfe sind wieder verwendbar, erweiterbar und wartbar. * Muster zeigen Ihnen, wie Sie Systeme mit guten OO-Entwurfseigenschaften entwerfen. * Muster sind bewährte objektorientierte Erfahrung. * Muster verschaffen Ihnen keinen Code, sie bieten Ihnen allgemeine Lösungen zu Entwurfsproblemen. Sie wenden diese auf spezifische Anwendung an. * Muster werden nicht erfunden, sie werden entdeckt. * Die meisten Muster und Prinzipien befassen sich mit Fragen der Änderungen an Software. * Die meisten Muster ermöglichen es, dass ein Teil des Systems unabhängig von allen anderen Teilen variieren kann. * Wir versuchen, in einem System das zu identifizieren, was sich ändert, um es zu kapseln. * Muster bieten eine gemeinsame Sprache, die Ihre Kommunikation mit anderen Entwicklern optimieren kann. ==== Observer ==== Definiert eine Eins-zu-viele-Abhängigkeit zwischen Objekten der Art, dass alle abhängigen Objekte automatisch benachrichtigt und aktualisier werden, wenn sich der Zustand des einen Objekts ändert. Punkt für Punkt: * Das Observer-Muster definiert ein Eins-zu-viele-Verhältnmis zwischen Objekten. * Subjekte oder, wie wir sie auch kennen, Observables aktualisieren Beobachter über eine gemeinsame Schnittstelle. * Die Beobachter sind insofern locker angebunden, als das Obervable über sie nichts anderes weiß, als dass sie das Interface Observer implementieren. * Sie können Daten aus dem Observable herausgeben oder herausziehen, wenn Sie das Muster verwenden (wobei das Herausziehen als die "richtigere" Methode betrachtet wird). * Verlassen Sie sich nicht auf eine bestimmte Reihenfolge der Benachrichtigung Ihrer Beobachter. ==== Decorator ==== Fügt einem Objekt dynamisch zusätzliche Verantwortlichkeiten hinzu. Dekorierer bieten eine flexible Alternative zur Ableitung von Unterklassen zum Zweck der Erweiterung der Funktionalität. Punkt für Punkt: * Vererbung ist eine Form von Erweiterung, aber nicht notwendigerweise der beste Weg, um Ihren Entwürfen Flexibilität zu verleihen. * Unsere Entwürfe sollten die Erweiterung von Verhalten ermöglichen, ohne dass dazu bestehender Code geändert werden müsste. * Oft können Komposition und Delegierung verwendet werden, um zur Laufzeit neue Verhalten hinzuzufügen. * Für die Erweiterung von Verhalten bietet das Decorator-Muster eine Alternative zur Ableitung von Unterklassen. * Das Decorator-Muster schließt einen Satz von Dekorierer-Klassen ein, die verwendet werden, um konkrete Komponenten einzupacken. * Dekorierer-Klassen spiegeln den Typ der Komponente wider, die sie dekorieren. (Sie haben tatsächlich den gleichen Typ wie die Komponente, die sie dekorieren, entweder durch Vererbung oder durch die Implementierung eines Interface.) * Dekorierer ändern das Verhalten der Komponente, indem sie vor und/oder nach (oder auch an Stelle von) Methodenaufrufen auf der Komponente neue Funktionalitäten hinzufügen. * Sie können eine Komponente mit einer beliebigen Zahl von Dekorierern einpacken. * Dekorierer sind für die Clients der Komponente überlichweise transparent, außer wenn sich der Client auf den konkreten Type der Komponente stützt. * Dekorierer können in Ihren Entwürfen zu vielen kleinen Objekten führen, und eine übermäßige Verwendung kann den Code unübersichtlich machen. ==== Factory ==== **//Factory Method//** Definiert eine Schnittstelle zur Erstellung eines Objekts, lässt aber die Unterklassen entscheiden, welche Klassen instantiiert werden. Factory Method ermöglicht einer Klasse, die Instantiierung in Unterklassen zu verlagern. **//Abstract Factory//** Bietet eine Schnittstelle zum Erstellen von Familien verwandter oder zusammenhängender Objekte an, ohne konkrete Klassen anzugeben. Punkt für Punkt: * Alle Factories kapseln die Objekt-Erstellung. * Die einfache Fabrik ist eine umkomlizierte Möglichkeit, Clients von konkreten Klassen zu entkoppeln, ist aber kein echtes Entwurfsmuster. * Factory Method stützt sich auf Vererbung: Die Objekterstellung wird an Unterklassen delegiert, die die Fabrikmethode implementieren, um Objekte zu erstellen. * Abstract Factory stützt sich auf Objekt-Komposition: Die Objekt-Erstellung ist in Methoden implementiert, die in der Fabrik-Schnittstelle vorgegeben ist. * Alle Factory-Muster fördern lockere Bindung, indem sie für Ihre Anwendung die Abhängigkeit von konkreten Klassen reduzieren. * Der Zweck von Factory-Method ist es, einer Klasse zu ermöglichen, die Instantiierung bis in ihre Unterklassen zu verzögern. * Der Zweck der Abstract Factory ist es, Familien verwandter Objekte zu erstellen, ohne dabei von den konkreten Klassen abhängig zu sein. * Das Prinzip der Umkehrung der Abhängigkeiten leitet uns an, Abhängigkeiten von konkreten Typen zu vermeiden und Abstraktion anzustreben. * Factories sind eine mächtige Technik, um auf Abstraktion statt auf konkrete Klassen zu implementieren. ==== Command ==== Kapselt einen Auftrag als ein Objekt und ermöglicht so, andere Objekte mit verschiedenen Aufträgen zu parametrisieren, Aufträge in Warteschlangen einzureihen oder zu protokollieren oder das Rückgängigmachen von Operationen zu unterstützen. Punkt für Punkt: * Das Command-Muster entkoppelt ein Objekt und versendet eine Auftrag an ein anderes, das weiß, wie es ihn ausführen muss. * Ein Befehl-Objekt steht im Zentrum dieses Entkoppelns und kapselt einem Empfänger mit einer Aktion (oder einer Gruppe von Aktionen). * Ein Aufrufer beauftragt ein Befehl-Objekt, indem er dessen ausführen()-Methode aufruft, die diese Aktion auf dem Empfänger aufruft. * Aufrufer können mit Befehlen sogar dynamisch zur Laufzeit parmetrisiert werden. * Befehle können das Rückgängimachen von Befehlen unterstützen, indem sie eine rückgängig()-Methode implementieren, die das Objekt in den Zustand zurückversetzt, der bestand, als die Methode ausführen() das letzte Mal aufgerufen wurde. * Makro-Befehle sind eine einfache Erweiterung des Command-Muster, die es ermöglichen, mehrere Befehle aufzurufen. Auch Makro-Befehle können problemlos eine Rückgänig-Operation unterstützen. * In der Praxis ist es nicht selten, das "kluge" Befehl-Objekte den Auftrag selbst implementieren, anstatt ihn an einen Empfänger zu delegieren. * Befehle können auch verwendet werden, um Loggings und Transaktionsysteme zu implementieren. ==== Adapter, Facade ==== **//Adapter//** Das Adapter-Muster konvertiert die Schnittstelle einer Klasse in die Schnittstelle, die der Client erwartet. Adapter ermöglichen die Zusammenarbeit von Klassen, die ohne nicht zusammenarbeiten könnten, weil sie inkompatible Schnittstellen haben. **//Facade//** Das Facade-Muster bietet eine vereinheitliche Schnittstelle für einen Satz von Schnittstellen eines Basissystems. Die Fassade definiert eine hochstufigere Schnittstelle, die die Verwendung des Basissystems vereinfacht. Punkt für Punkt: * Nehmen Sie Adapter, wenn Sie eine bestehende Klasse verwenden müssen und ihre Schnittstelle nicht der entspricht, die Sie benötigen. * Verwenden Sie Facade, wenn Sie eine größere Schnittstelle oder eine komplexe Menge von Schnittstellen vereinfachen müssen. * Ein Adapter ändert eine Schnittstelle in die, die ein Client erwartet. * Eine Fassade entkoppelt eine Client von einem komplexen Basissystem. * Je nach Größe und Komplexität einer Ziel-Schnittstelle kann es etwas Arbeit sein, einen Adapter zu implementieren. * Bei der Implementierung einer Fassade ist es erforderlich, dass man die Fassade mit ihrem Basissystems zusammensetzt und Delegierung verwendet, um die Arbeit der Fassade durchzuführen. * Es gibt zwei Formen des Adapter-Musters: Objekt- und Klassen-Adapter. Für Klassen-Adapter ist Mehrfachvererbung erforderlich. * Für ein Basissystem können Sie mehr als eine Fassade implementieren. * Ein Adapter umhüllt ein Objekt, um seine Schnittstelle zu ändern, ein Dekorierer umhüllt ein Objekt, um neue Verhalten und Verantwortlichkeiten hinzuzufügen, eine Fassade umhüllt einen Satz von Objekten, um die Schnittstelle zu vereinfachen. ==== Template Method ==== Definiert in einer Methode das Gerüst eines Algorithmus und überlässt einige Schritte den Unterklassen. Template Method erlaubt Unterklassen, bestimmte Schritte des Algorithmus neu zu definieren, ohne die Struktur des Algorithmus zu ändern. Punkt für Punkt: * Eine "Template-Methode" definiert die Schritte eines Algorithmus und überlässt die Implementierung dieser Schritte den Unterklassen. * Das Template Method-Muster liefert uns eine wichtige Technik für die Code-Wiederverwendung. * Die abstrakte Klasse der Template-Methode kann konkrete Methoden, abstrakte Methoden und Hooks definieren. * Abstrakte Methoden werden von den Unterklassen implementiert. * Hooks sind Methoden, die in der abstrakten Klasse nichts tun oder nur ein Default-Verhalten anbieten, aber in den Unterklassen überschrieben werden können. * Um zu verhindern, dass Unterklassen den Algorithmus in der Template-Methode ändern, wied die Template-Methode als final deklariert. * Das Hollywood-Prinzip leitet uns an, Entscheidungsprozesse in Highlevel-Module zu packen. Diese entscheiden, wie und wann die Lowlevel-Module aufgerufen werden. * Sie werden Code aus dem wirklichen Leben auf viele Verwendungen des Template Method-Musters stoßen, dürfen aber (wie bei jedem Muster) nicht erwarten, dass diese so entworfen sind, wie die Theorie sie beschreibt. * Die Muster Strategy und Template Method kapseln beide Algorithmen, das ein über Vererbung und das andere über Komposition. * Factory Method ist eine Spezialisierung von Template Method. ==== Iterator ==== Bietet eine Möglichkeit, auf die Elemente in einem Aggregat-Objekt sequenziell zuzugreifen, ohne die zu Grunde liegende Implementierung zu offenbaren. Punkt für Punkt: * Ein Iterator ermöglicht Zugriff auf die Elemente eines Aggregats, ohne seine interne Struktur zu offenbaren. * Ein Iterator übernimmt die Aufgabe, über ein Aggregat zu iterieren, und kapselt es in einem anderen Objekt. * Wenn wir einen Iterator verwenden, erlösen wir das Aggregat von der Verantwortung, Operationen für die Durchquerung seiner Daten zu Verfügung zu stellen. * Ein Iterator bietet eine allgemeine Schnittstelle für die Durchquerung der Elemente eines Aggregats und ermöglicht es Ihnen, beim Schreiben von Code, der die Elemente eines Aggregats verwendet, Polymorphismus zu verwenden. * Wir sollen danach streben, dass jede Klasse nur eine Verantwortlichkeit zugewiesen wird. ==== Composite ==== Ermöglicht Ihnen, Objekten zu einer Baumstruktur zusammenzusetzen, um Teil/Ganzes-Hierarchien auszudrücken. Das Composite-Muster erlaubt den Clients, individuelle Objekte und Zusammensetzungen von Objekten auf gleiche Weise zu behandeln. Punkt für Punkt: * Das Composite-Muster bietet eine Struktur, die einzelne Objekte und Komposita aufnehmen kann. * Das Composite-Muster erlaubt Clients, Komposita und einzelne Objekte auf gleiche Weise zu behandeln. * Jedes Objekt in einer zusammengesetzten Struktur ist eine Komponente. Komponenten können andere Komponenten oder Blattknoten sein. * Bei der Implementierung von Composite gibt es viele Designkompromisse. Sie müssen eine Ausgleich zwischen Transparent und Sicherheit und Ihren Anforderungen finden. ==== Zusammengesetzte Muster ==== Ein zusammengesetztes Muster kombiniert zwei oder mehrere Muster zur einer Lösung für ein wiederkehrendes oder allgemeines Problem. Punkt für Punkt: * Das Model-View-Controller-Mustger (MVC) ist ein zusammengesetztes Muster, bestehend aus Observer-, Strategy- und Composite-Muster. * Das Model nutzt das Observer-Muster; so kann es Beobachter auf dem aktuellen Stand halten und dennoch von ihnen entkoppelt bleiben. * Der Controller ist das Strategy-Objekt für den View. Der View kann verschiedene Implementierungen des Controllers benutzen, um unterschiedliches Verhalten zu zeigen. * Der View nutzt das Composite-Muster für die Implementierung der Benutzerschnittstelle. Diese besteht in der Regel aus verschachtelten Komponenten wie Panels, Frames und Buttons. * Diese Muster arbeiten zusammen, um die drei Akteure im MVC-Model zu entkoppeln. So bleibt das Design klar und flexibel. * Mit dem Adapter-Muster lässt sich ein neues Model an ein vorhandenes View/Controller-Paar anpassen. * Model 2 ist ein Anpassung des MVC für Webanwendungen. * Im Model 2 ist der Controller als Servlet implementiert und der View als JSP & HTML. ===== Links ===== * [[http://www.namespace-cpp.de/std/doku.php/kennen/begriffe#dokuwiki__top|Begriffe aus C++ und OO]] * [[http://hillside.net/europlop/HillsideEurope|Hillside Group]] * [[http://c2.com|Cunningham & Cunningham]] * [[http://c2.com/ppr|Portland Pattern Repository]] * [[http://wiki.c2.com/?CategoryPattern|C2 Pattern Catalog]] * [[http://wiki.c2.com/?AntiPatternsCatalog|C2 Anit Patterns Catalog]]