Definieren von Objekt-Beziehungenamrhein/ADP/Struktur.pdf · 2017-08-08 · 4 Szenario/Problem Auf...
Transcript of Definieren von Objekt-Beziehungenamrhein/ADP/Struktur.pdf · 2017-08-08 · 4 Szenario/Problem Auf...
Strukturmuster
Definieren von Objekt-Beziehungen
2
Einleitung Strukturmuster beschreiben die
Zusammensetzung und die Beziehungen von Klassen und Objekten zu grösseren Strukturen.o Sie legen fest, welche Beziehungen Klassen
untereinander haben und was ihre Verantwortlichkeiten sind.
o Strukturmuster, welche sich auf Objekte beziehen, legen fest, welche konkreten Instanzen einer bestimmten Klasse gebildet werden.
Beispiele: Fassade, Adapter, Proxy, Decorator, Bridge, …
Fassade
Vereinfachte Schnittstelle
3
4
Szenario/Problem
Auf ein Subsystem mit komplexer innerer Struktur wird ein Zugriff benötigt.
Dies soll möglich sein, ohne den Clients die Details des Subsystems (Paket/Komponente) bekannt zu geben.
(Zu) viele verschiedene Zugriffe von aussen, komplex, unübersichtlich, …
5
Mögliche Lösung Das Fassade Design Pattern definiert eine
einfache Schnittstelle zur Benutzung eines Systems oder einer Menge von Objekten.
Eine Fassade vereinfacht den Zugriff auf ein komplexes Subsystem oder auf eine Menge zusammengehörender Objekte.
6
Anwendung des Pattern Das Fassade Pattern versteckt die Komplexität
des Subsystems und stellt den Clients eine Schnittstelle für die Benutzung des Subsystems zur Verfügung.
Mit dieser Schnittstelle können alle Clients uniform auf das System zugreifen.
Das Fassademuster fügt eine einzige neue Klasse zum Subsystem hinzu.
Die Fassade leitet alle von den Clients benötigten Methoden an die internen Systemklassen weiter.
7
Lösung/Implementation
Konkretes Beispiel: Fassade für ein Bookingsystem.
8
Lösung/Implementation
Fassade implementiert die vereinfachende
Schnittstellenfunktiondelegiert die auszuführenden Aufgaben an die
beteiligten Klassen des Subsystems weiter
Klassen im Paket implementieren die verschiedenen Dienste und
Methodendiese sind meistens nur im Paket (intern)
sichtbar (package)
9
Lösung/Struktur/Implementation
public class BookingFacade {
private Reservation reservation = new Reservation(); private Payment payment = new Payment(); private Confirmation confirmation = new Confirmation();
public String book(long eventId, long seatId) { String amount = reservation.reservate(eventId, seatId); payment.doPayment(amount); String message = confirmation.confirm(eventId, seatId); return message; }
}
10
Lösung/Struktur/Implementation
public class Reservation {
public String reservate(long eventId, long seatId) { // hier waere die Business Logik fuer die Reservation ... return "200"; }}
public class Payment {
public String doPayment(String amount) { // hier waere die Business Logik fuer die Bezahlung... return "ABC-1865227"; }}
public class Confirmation {
public String confirm(long eventId, long seatId) { // hier waere die Business Logik fuer das Bestaetigen via email ... return "Ok"; }}
11
Lösung/Struktur/Implementation
public class FacadeSampleApplication {
public static void main(String[] args) {BookingFacade bookingFacade = new BookingFacade();
bookingFacade.book(1,255);
}}
12
Vorteile Vereinfachte Schnittstelle. Der Client kann ein komplexes System einfach
verwenden, ohne die Klassen des Systems zu kennen. Entkopplung des Client vom Subsystem: Da die Clients
nur mit der Fassade arbeiten sind sie unabhängig von Änderungen im Subsystem.
Wartungen und Modifikationen am Subsystem bedeuten nur Änderungen innerhalb des Systems und ev. der Fassade.
Nachteile Eine zusätzliche Klasse mit zusätzlichen Methoden (Indirektion verlangsamt den Code)
13
Verwendung
Das Fassade Pattern ist sinnvoll anwendbar wenn ein neu zu erstellendes System/Subsystem mit
vielen unterschiedlichen Methoden in nicht verwandten Klassen von aussen benutzbar sein soll
sich die Schnittstelle auf das Subsystem nicht/nur selten ändert
sich die Signaturen der Methoden in diesen Klassen nicht / nur selten ändern
14
Praxisbeispiel Microservice-Fassade
Quelle: https://github.com/strongloop/loopback-example-facade/wiki/The-Microservice-Facade-Pattern
15
Verweis auf andere Muster
Verwandte Muster sind Adapter Pattern
- Umwandlung in „etwas anderes“ Wrapper Pattern
- Schnittstelle zu bestehendem Alt-System (z.B. nicht OO)
Bridge Pattern- Bridge entkoppelt eine Abstraktion
(Schnittstelle) von ihrer konkreten Implementierung (zweiseitige Verbindung / Unabhängigkeit).
Adapter
Schnittstellen-Anpassung
16
17
Szenario/Problem
Eine bestehende Menge von Klassen, eine Werkzeugsammlung oder eine Klassenbibliothek soll verwendet werden.
Die Schnittstelle der bestehenden Klassen oder Bibliotheken entspricht nicht der vom Client benötigten Schnittstelle.
18
Mögliche Lösung Das Adapter Design Pattern implementiert eine
Schnittstelle zum übersetzen der Anfragen in die Schnittstelle des vorhandenen Systems oder einer Klassenbibliothek.
19
Anwendung des Pattern Bibliotheken stellen ihre Dienste durch klar
definierte Schnittstellen zur Verfügung, welche nicht geändert werden sollen oder nicht geändert werden können.
Das Adapter Pattern kann benutzt werden, um bestehende Klassen oder Bibliotheken zu benutzen.
Der Adapter ermöglicht die Kommunikation zwischen nicht kompatiblen Schnittstellen.
20
Lösung/Implementation
Konkretes Beispiel: Adapter für eine existierende (-Bibliotheks)-Klasse
21
Lösung/Implementation
Konkretes Beispiel: Adapter für eine existierende Person(-Bibliotheks)-Klasse
22
Lösung
Adapter- implementiert die öffentlichen (public)
Schnittstellenfunktionen- übersetzt die Anfrage in die Schnittstelle der
Bibliothek und leitet die auszuführende Aufgaben an eine oder mehrere Klassen der Bibliothek
- übersetzt die so erhaltene Antwort in den korrekten Ziel-Typ.
23
Lösung/Struktur/Implementation
public class PersonAdapter{ private Person person;
public void setValid(boolean b) { if(b)
person.setValid(); else
person.setInvalid(); }
public String getName() { return person.getFirstname() + " " +
person.getLastName(); }
. . . }
24
Vorteile Der Client kann ein bestehendes System einfach
verwenden, ohne dass die Klassen des Systems angepasst werden müssen.
Es können Methoden verwendet werden, welche nicht der Ziel-Schnittstelle entsprechen (falsche Signatur/falscher Typ).
Austausch der Bibliothek einfach möglich (unter ev. Anpassung der Adapter-Klasse).
25
Nachteile (Indirektion verlangsamt ev. den Code)
Klassenhierarchie ist schwierig abzubilden (z.B.
Klasse Employee abgeleitet von Person).
26
Verwendung
Das Adapter Pattern ist sinnvoll anwendbar wenn
viele Methoden in bestehenden Klassen oder Bibliotheken benutzt werden sollen.
sich die Schnittstelle auf das die Bibliothek nicht/nur selten ändert.
Die Bibliothek flexibel austauschbar sein soll.
27
Praxisbeispiel Fassade/Adapter
Quelle: Software-Referenzarchitektur des EJPD
28
Verweis auf andere Muster
Verwandte Muster sind Wrapper Pattern
- Schnittstelle zu bestehendem Alt-System (z.B. nicht OO)
Proxy- kontrolliert den Zugang zu einer
Komponente oder einem Subsystem (Security)
Fassade- Schnittstelle in Paket oder Subsystem
29
ÜbungIm setter für Telefonnummer die Nummer validieren und formatieren:
public void setTelefonnummer(String telefonnummer) { // hier die Telefonnummer pruefen,formatieren und zuweisen, z.B.
this.telefonnummer = ???.validateAndFormatNumber(telefonnummer);}
Validieren und formatieren mit Google libphonenumber-Bibliothek, aber ohne dass Klasse Vereinsmitglied eine Abhängigkeit auf die Google Library hat. Google lib soll später ausgetauscht werden können, ohne dass Code in Vereinsmitglied ändert.
Proxy
Stellvertreter
30
31
Szenario/Problem
Der Zugriff auf ein Objekt soll aus einem (oder mehreren Gründen) auf einen Stellvertreter umgeleitet werden.
Gründe dafür können sein:a. Ein Objekt soll gegen unberechtigten Zugriff
geschützt werden.b. Der Zugriff auf ein Objekt soll aufgezeichnet
werden (Logging) .
c. Das benötigte Objekt ist nicht lokal verfügbar/vorhanden.
d. Ein grosses, komplexes Objekt soll nicht als ganzes, sondern es sollen nur die benötigten Teile davon geladen werden.
32
Mögliche Lösung Das Proxy Design Pattern implementiert einen
lokalen Stellvertreter (Remote Proxy) zum Weiterleiten oder Filtern der Anfragen.
Geeignet als Lösung für a, b und c
33
Mögliche Lösung Das Proxy Design Pattern implementiert einen
virtuellen Stellvertreter (Virtual Proxy) zum Filtern oder Verzögern der Anfragen (z.B. verzögertes Speichern).
Geeignet als Lösung für a, b und d
34
Anwendung des Pattern Ein Proxy (Stellvertreterobjekt) kann verwendet
werden um- Technische Aspekte hinzuzufügen, z.B.
Transaktionen, Security, Logging, ... - einen Zugriff auf „ferne“ Objekte zu bieten
(remote/über ein Netzwerk).- die Kosten für das Erzeugen komplexer Objekte
zu senken (z.B. durch dessen Verzögerung oder Vermeidung).
- den Zugriff auf Objekte aufzuzeichnen.
35
Lösung/Implementation
Proxy als Stellvertreter für ein reales Objekt.
36
Lösung/Implementation
Der Proxy- implementiert die öffentlichen
Schnittstellenfunktionen- erweitert oder filtert die Anfrage und leitet die
auszuführende Aufgaben (falls nötig) an das reale Objekt weiter.
- gibt die erhaltene Antwort an den Client zurück.
Reales Objekt- bietet verschiedene Dienste und Methoden
37
Lösung/Struktur
Image Proxy als Stellvertreter für ein reales Image Objekt.
Verzögerte Anzeige mit „Ersatzbild“ während des Ladens.
38
Lösung/Implementation
public class Proxy { private Image image;
public Dimension getSize(boolean b) { return image.Size() }
public void paint() { if(image != null) image.paint(); else { Anzeige: "Bild ist am Rendern…" Lade Bild in separatem Thread } }
. . . }
39
Vorteile Der Proxy kann bestehende Objekte gegen
unerlaubten Zugriff schützen, ohne dass das Objekt verändert werden muss.
Der Proxy kann die Funktionalität eines bestehenden Objekts einfach erweitern (Nebeneffekte).
Für den Client ist der Zugriff transparent. Ein Austausch des realen Objekts ist einfach möglich.
Nachteil Verlangsamung durch Indirektion.
40
Verwendung
Das Proxy Pattern kann verwendet werden, um bestehende Klassen/Objekte um gewisse Funktionalitäten wie Zugriffsschutz, Logging, verzögertes Laden, Remote-Zugriff, …zu erweitern.
Wird extensiv in Spring und Java Enterprise Edition eingesetzt.
41
Praxisbeispiel: Spring Transactions
Quelle: https://spring.io/blog/2012/05/23/transactions-caching-and-aop-understanding-proxy-usage-in-spring
42
Praxisbeispiel: Security Proxy
Quelle: Software-Referenzarchitektur des EJPD
43
Verweis auf andere Muster
Verwandte Muster sind (neben den bereits erwähnten)
Decorator- Dynamische Erweiterung von Klassen
um neue Funktionalität
Decorator
Funktionale Erweiterung
44
45
Szenario/Problem
Die Funktionalität von Objekten soll möglichst flexibel verändert oder erweitert werden können, ohne dass die Klasse geändert werden soll.
Gründe dafür können sein:a. Ein Objekt soll weitere Informationen zur
Verfügung stellenb. Ein Objekt soll weitere Dienste zur Verfügung
stellen.
c. Die bestehende Funktionalität eines Objekts soll flexibel angepasst oder erweitert werden können.
46
Szenario/Problem Es soll möglich sein, Dokumente oder
Bilder auf verschiedenste Art herzustellen:- Mit schmalem, mittlerem oder grossem
Rand- Kompakt oder hochauflösend- Mit oder ohne Border-Linien- Mit oder ohne Hintergrundfarbe- Mit oder ohne Wasserzeichen
47
Mögliche Lösung Das Decorator Design Pattern verwendet
verschiedene Komponenten, welche die unsprüngliche Komponente um zusätzliche Eigenschaften oder Funktionalität erweitern (aber ohne die Verwendung von Generalisierung!)
Dekorationen des FileInputStream in der Java LibraryQuelle: http://www3.ntu.edu.sg/home/ehchua/programming/java/j5b_io.html
48
Lösung/Struktur Der Methodenaufruf auf den Dekorierer wird vor den Aufruf
auf die zu dekorierende Komponente geschaltet. Der Dekorierer hat die gleiche Schnittstelle wie die zu
dekorierende Komponente. Aufrufe an den Dekorierer können entweder weitergeleitet
oder in der Komponente selber verarbeitet werden. Der Dekorierer ist dabei für den Aufrufer (Client)
transparent, der Client sieht den Dekorierer nicht.
49
Lösung/Struktur Das Interface definiert die
öffentliche Schnittstelle für die zu dekorierenden Objekte.
Der abstrakte Decorator hält eine Referenz auf die Komponente und implementiert sie gleich wie die Komponente.
Die konkreten Decorator implementieren die speziellen Operationen/Zusatz-Dienste.
50
Implementation
public interface IRenderer{ void render();}
51
Implementationpublic class Document : IRenderer{ public void render() { // render document Console.WriteLine("Render Document"); }}
public class Image : IRenderer{ public void render() { // render image Console.WriteLine("Render Image: "); }}
52
Implementationpublic abstract class DocumentDecorator : IRenderer{ protected IRenderer decoratedRenderer;
public DocumentDecorator(IRenderer decoratedRenderer) { this.decoratedRenderer = decoratedRenderer; }
virtual public void render() { decoratedRenderer.render(); }}
53
Implementationpublic class BorderDecorator : DocumentDecorator{ public BorderDecorator(IRenderer decoratedRenderer) :
base(decoratedRenderer) {}
override public void render() { decoratedRenderer.render(); setBorder(decoratedRenderer); }
private void setBorder(IRenderer decoratedRenderer) { // render border Console.WriteLine("-------------------------------"); Console.WriteLine("setBorder"); Console.WriteLine("-------------------------------"); }}
54
Implementationpublic class BackgroundDecorator : DocumentDecorator{ public BackgroundDecorator(IRenderer
decoratedRenderer) : base(decoratedRenderer)
{ }
override public void render() { decoratedRenderer.render(); setBackground(decoratedRenderer); }
private void setBackground(IRenderer decoratedRenderer) { // set Color Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Set Foreground red"); }}
55
ImplementationIRenderer document = new Document();document.render();
IRenderer borderedDocument = new BorderDecorator(new Document());
borderedDocument.render();
IRenderer colorborderImage = new BorderDecorator(new BackgroundDecorator(new Image()));
colorborderImage.render();
56
Vorteile Die zu dekorierende Klasse ist beliebig (so lange sie
die Schnittstelle implementiert). Für den Client ist der Zugriff transparent. Ein Austausch des realen Objekts ist einfach möglich. Mehrere Decorator können hintereinander
geschachtelt werden. Lange und unübersichtliche Vererbungshierarchien
können vermieden werden. Jeder Decorator repräsentiert genau seine Funktion
(und nichts sonst) -> einfacher, wartbarer Code.
57
Nachteile Erschwerte Fehlerfindung bei langen, versteckten
Aufrufketten von dekorierten Objekten. Viele Klassen und Objekte, da für jedes Feature
ein neuer Dekorierer gebraucht wird. Das dekorierte Objekt hat nicht die gleiche
Identität wie das ursprüngliche Objekt, Vorsicht bei Aufruf von equals().
58
Praxisbeispiel: Angular Decorator@Component({ selector: 'app-recipe-detail', templateUrl: './recipe-detail.component.html', styleUrls: ['./recipe-detail.component.css']})export class RecipeDetailComponent implements OnInit { @Input() recipe: Recipe;
constructor() { }
ngOnInit() { }
}
59
Verweis auf andere Muster
Verwandte Muster sind (neben den bereits erwähnten)
Pipes and FilterKette von Objekten (Filtern), welche die
zusätzlichen Anfragen oder Aufgaben hintereinander ausführen.
60
Übung
Ordnen Sie die Aussagen den Pattern zu:
Fassade Fungiert als Stellvertreter für das reale Objekt
Adapter Konvertiert ein Interface in ein anderes
Proxy Belässt das Interface unverändert, aber addiert Zusatzfunktionalität
Decorator Vereinfacht den Zugriff auf ein Subsystem
Zusammenfassung
Vergleich
61
62
Kurzbeschreibung Ein Adapter passt eine
existierende Schnittstelle an die vom Client benötigte Schnittstelle an.
Eine Fassade vereinfacht den Zugriff auf ein komplexes Subsystem.
Ein Decorator fügt einer Komponente dynamisch neue Funktionalität zu.
Ein Proxy ist ein Platzhalter für ein anderes Objekt.
63
Unterscheidungsmerkmale Eine Fassade erzeugt ein neues Interface, ein Adapter
benutzt ein bestehendes Interface (und wandelt es um).
Ein Adapter ermöglicht die Benutzung bestehender Software auf eine «neue» Art.
Eine Fassade leitet eine Anfrage weiter, ein Adapter wandelt ein Objekt (Anfrage/ Antwort) um.
Ein Proxy erweitert die Funktionalität (einmalig) und behält dabei die Schnittstelle (keine Umwandlung).
Ein Decorator erweitert die Funktionalität rekursiv bei gleicher Schnittstelle und ohne Ableitung (subclassing).