Premium Partner

POSA 1 - Part 3

Pattern-Oriented Software Architecture

Pattern-Oriented Software Architecture

Nicht sichtbar

Nicht sichtbar

Kartei Details

Karten 7
Sprache Deutsch
Kategorie Informatik
Stufe Universität
Erstellt / Aktualisiert 30.12.2015 / 09.01.2016
Lizenzierung Keine Angabe    (Jeyanthan Ravindran)
Weblink
https://card2brain.ch/box/posa_1_part_3
Einbinden
<iframe src="https://card2brain.ch/box/posa_1_part_3/embed" width="780" height="150" scrolling="no" frameborder="0"></iframe>

Whole Part

Das Whole-Part Design Pattern hilft bei der Zusammenführung von kleineren Teilen, die gemeinsam eine grössere Einheit bilden. Eine zusammengesetzte Komponente «Whole» kapselt die einzelnen Komponenten «Parts», Koordiniert die Zusammenarbeit und bietet ein gemeinsames Interface für die Funktionalität. Ein direkter Zugriff auf die einzelnen
Parts ist von aussen nicht möglich. Beispiel: In einem CAD kann man Objekte modellieren (siehe Bild. Ein modelliertes Auto besteht aus vielen kleineren Objekten wie Räder, Scheiben, usw., welche dann aus noch kleineren Teilen bestehen. Das Auto Objekt jedoch ist zuständig für Aktionen am Auto als ein Ganzes, wie z.B. das Rotieren.

Problem In fast jedem Softwaresystem gibt es zusammengesetzte Objekte. Moleküle in einer Chemie-Simulation können als ein Graph von separaten Atomen implementiert werden. Durch die Zusammensetzung entsteht ein neues Objekt, welches mehr ist als nur eine Ansammlung von Atomen. Dieses Objekt hat Attribute und Methoden, welche nur für
das Gesamtobjekt, aber nicht für die Einzelteile gelten sollen. Es muss also ein Interface geben um die Gesamtheit des Objektes zu steuern.

Lösung
Beim Whole-Part-Pattern wird zwischen drei verschiedenen Beziehungstypen unterschieden:

  • Assembly-Parts Relationship
    Die Struktur des ganzen ist streng vorgegeben, wie z.B. bei einem Auto. Die Anzahl und Art einzelner Parts ist definiert und ändert nicht.
  • Container-Content Relationship
    Die Teile sind nicht so Eng gekuppelt wie beim assembly-parts. Es können dynamisch (zur Laufzeit) Teile hinzugefügt oder entfernt werden.
  • Collection-Member Relationship
    Dies ist eine Spezialisierung von Container-Content Relationship. Die Collection gruppiert ähnliche Teile. Es wird kein Unterschied zwischen den einzelnen Teilen gemacht, alle werden gleich behandelt.

Whole Part

Struktur

Whole Repräsentiert eine Zusammensetzung von kleineren Objekten (Parts). Das Whole benützt die Funktionalität der Parts, um seine Services zu implementieren. Manche Methoden rufen direkt Services des Parts auf und liefern dessen Antwort an den Client. Andere implementieren komplexere Abläufe, welche auf mehreren kleinere Services auf den Parts zurückgreift. Das Whole verhaltet sich als ein Wrapper um die einzelnen Objekte und verbietet den direkten Zugriff.

Part Repräsentiert ein bestimmtes Objekt und dessen Services. Ein Part gehört exakt zu einem Whole. Der Lebenszyklus des Parts ist an den Lebenszyklus des Whole gebunden (Komposition).

Master-Slave Pattern

Das Master-Slave Pattern erhöht die Fehlertoleranz und Exaktheit eines Systems und erlaubt es die Teilresultate parallel zu Berechnungen. Eine Master Komponente verteilt die Arbeit auf identische Slave Komponenten auf und aggregiert die Teilresultate zum Gesamtresultat. Für den Client ist die Aufteilung transparent.

Beispiel: Das Traveling Salesman Problem: Es soll eine optimale Route zwischen einem Set von definierten Orten gefunden werden, sodass jeder Ort nur einmal besucht wird. Dies ist ein NP-vollständiges Problem. Die meisten existierenden Implementationen berechnen deshalb nur eine Approximation des Resultats. Eine einfache Approximation
wäre das zufällige Selektieren von Routen, welche miteinander verglichen werden, um so eine möglichst effiziente Route zu erhalten. Eine mögliche Approximation kann mit Hilfe von Divide And Conquer berechnet werden, in dem jeweils nur eine Teilroute berechnet wird.

Context Partitionieren von Arbeit in semantisch identische Teilaufgaben.

Problem «Divide And Conquer» ist ein Prinzip, welches zur Lösung vieler unterschiedlicher Probleme eingesetzt werden kann. Die Arbeit wird in mehrere gleichartige Teilaufgaben aufgeteilt, welche dann unabhängig voneinander abgearbeitet werden. Das Endresultat wird aus den einzelnen Resultaten der Teilaufgaben berechnet.

Forces
• Clients sollen nicht merken, dass die Berechnung aufgeteilt wird.
• Weder Clients noch Berechnungen von Teilaufgaben sollten vom Algorithmus, der für das Partitionieren der Arbeit und das Berechnen des finalen Resultats zuständig ist, abhängig sein.
• Es kann hilfreich sein, unterschiedliche, jedoch semantisch identische Implementationen für das Abarbeiten der Teilaufgaben zu benutzen (z.B. um die Berechnungsgenauigkeit zu erhöhen).
• Das Abarbeiten von Teilaufgaben kann zusätzliche Koordination benötigen.

Lösung
Es wird eine Koordinationsstelle zwischen den Clients des Services und dem Abarbeiten der individuellen Teilaufgaben eingeführt. Die Master Komponente teilt die Arbeit in identische Teilaufgaben auf auf, delegiert die Teilaufgaben an unterschiedliche unabhängige, jedoch identische Slave Komponenten und berechnet das Endresultat aus den
partiellen Resultaten.

Master-Slave Anwendungstypen

Dieses allgemeine Prinzip wird primär in folgenden drei Gebieten angewendet.

Fehlertoleranz Das Ausführen eines Aufgabe wird an unterschiedliche, replizierte Implementationen delegiert. Das erste Resultat wird an den Aufrufer zurück gegeben. Dadurch kann der Ausfall einer Komponente toleriert werden.

Parallele Berechnungen Ein komplexer Task kann in identische Teilaufgaben aufgeteilt werden, welche parallel mit unterschiedlichen Daten ausgeführt werden. Das finale Resultat wird aus den Teilresultaten berechnet.

Rechengenauigkeit Eine Berechnung wird an mehrere unterschiedliche Implementationen delegiert. Die einzelnen Implementationen können speziell für einzelne Anwendungsfälle ausgelegt sein. Aus sämtlichen Resultaten wird versucht ein möglichst genaues Resultat zu erhalten.

Master-Slave Struktur

Master Stellt den Service zur Verfügung, der das «Divide And Conquer» Prinzip einsetzt. Offeriert ein Interface, über welches die Clients zugreifen können. Implementiert Funktionen für das Partitionieren der Arbeit in Teilaufgaben, Starten und Kontrollieren der Prozesse und das Berechnen des finalen Resultats. Verwaltet die Referenzen zu allen Slave Instanzen.

Slave Zuständig für die Berechnung einer Teilaufgabe. Es sind mindestens zwei Slave Instanzen mit der Master Komponente verbunden.

Proxy Pattern

Das Proxy Design Pattern lässt Clients einer Komponente mit einem Repräsentanten anstelle der echten Komponente kommunizieren. Dadurch kann vor sowie nach der Ausführung zusätzliches Verhalten zur echten Komponente hinzugefügt werden (Decorator) oder der Zugriff kann geschützt werden.

Problem Der direkte Zugriff auf eine Komponente kann problematisch sein, wenn z.B. die Örtlichkeit der Komponente nicht hard codiert werden soll. Der direkte Zugriff verunmöglicht zudem das Hinzufügen von weiteren Funktionen.

Forces
• Der Zugriff auf die Komponente soll effizient sein.
• Der Zugriff auf die Komponente soll für den Client einfach und transparent erfolgen. Der Aufruf der Komponente soll sich daher nicht von einem direkten Aufruf unterscheiden.
• Dem Client sollte es dennoch bewusst sein, dass ein Aufruf zu Performance-Einbussen führen kann (z.B. remote call).

Lösung Der Client arbeitet mit einer Repräsentation des Originals, dem Proxy. Der Proxy bietet die selbe Schnittstelle wie das Original an, kann jedoch noch weitere Funktionalitäten vor sowie nach der Durchführung der eigentlichen Operation vornehmen.

Struktur
Abstract Original Das Abstract Original definiert die Signatur für das original Objekt.
Original Das Original implementiert Abstract Original und ist der Service, welcher dem Client angeboten werden soll
Proxy Der Proxy implementiert ebenso das Abstract Original. Er hält intern eine Referenz auf das Original (oder wird, bei Lazy initialization, hierbei kann es sich uch um eine URI handeln). Vor sowie nach dem Aufruf kann der Proxy zusätzliche
Funktionen ausführen. Die eigentliche Operation wird jedoch an das Original delegiert.
Client Der Client möchte den Dienst des Original beziehen.

Proxy Anwendungstypen (Varianten)

Remote Proxy Der Remote-Proxy nimmt die Kapselung der Inter-Prozess-Kommunikation vor. Er führt das (Un-) Marshalling der Anfragen vor und löst den Remote-Dienst auf. Siehe auch Broker.

Protection Proxy (Schutz für Original) Der Protection-Proxy schützt das Original vor unberechtigten Zugriff. Vor jedem Aufruf einer Dienstmethode wird eine Berechtigungsprüfung durchgeführt.

Cache Proxy Der Cache-Proxy speichert die Resultate der Original-Methoden. Bei erneuten Aufrufen gibt der Proxy den zwischengespeicherten Wert zurück. Für das Zurücksetzen wird eine Refresh-Strategie benötigt.

Synchronization Proxy Der Synchronization-Proxy synchronisiert den Zugriff auf das Original, z.B. Collections.synchronizedCollection.

Counting Proxy Der Counting Proxy zählt die Anzahl Referenzen oder Aufrufe. Mittels der Anzahl Referenzen kann sichergestellt werden, dass ein Objekt auf dem Heap z.B. in C++ nach Freigabe der letzten Referenz de alloziert wird.

Virtual Proxy Auch bekannt unter Lazy-Proxy. Der Virtual Proxy lädt nicht das gesamte Original bei der Erstellung des Proxies. Z.B. können Bilddaten erst beim ersten Zugriff nachgeladen werden.

Firewall Proxy (Schutz für Client) Der Firewall-Proxy schützt den Client vor den Rückgabewerten des Original. Dies ist angebracht, wenn das Original von einer nicht vertrauenswürdigen Quelle ist.