- 1. Ziele
- 2. Probleme
- 3. Motivation
- 4. Diskussion
- 5. Struktur
- 6. Beispiel
- 7. Kontrollliste
- 8. Faustregeln
Ziele
- Trennen Sie die Abstraktion von ihrer Implementierung, damit sie sich unabhängig voneinander ändern können.
- Erstellen Sie eine öffentliche Schnittstelle in einer Vererbungshierarchie und implementieren Sie sie in Ihrer eigenen Vererbungshierarchie.
- Zusätzlich zur Kapselung, die Verwendung von Isolation
Probleme
"Stärken von Programmierbeziehungen" durch Verwenden einer Unterklasse einer abstrakten Basisklasse, um alternative Implementierungen bereitzustellen. Dadurch wird die Bindung zur Kompilierzeit zwischen Schnittstelle und Implementierung blockiert. Abstraktion und Implementierung können nicht unabhängig voneinander erweitert oder neu definiert werden.
Motivation
Betrachten Sie den Bereich „Thread Scheduling“.
Es gibt zwei Arten von Thread-Schedulern, zwei Arten von Betriebssystemen oder "Plattformen". Angesichts dieses Spezialisierungsansatzes müssen wir für jede dieser beiden Varianten eine Klasse definieren. Wenn wir eine neue Plattform hinzufügen (z. B. die Java Virtual Machine), wie würde unsere Hierarchie aussehen?
Was wäre, wenn wir drei Arten von Thread-Schedulern und vier Arten von Plattformen hätten? Was wäre, wenn wir fünf Arten von Thread-Schedulern und zehn Arten von Plattformen hätten? Die Anzahl der Klassen, die wir definieren müssten, ergibt sich aus der Anzahl der Scheduling-Schemata und der Anzahl der Plattformen.
Das Bridge-Entwurfsmuster schlägt vor, diese exponentiell explosive Vererbungshierarchie in zwei orthogonale Hierarchien umzugestalten – eine für plattformunabhängige Abstraktionen und eine für plattformabhängige Implementierungen.
Diskussion
Zerlegen Sie die Schnittstelle und Implementierung der Komponente in orthogonale Klassenhierarchien. Eine Schnittstellenklasse enthält einen Zeiger auf eine abstrakte Implementierungsklasse. Dieser Zeiger wird mit einer Instanz der konkreten Klasse initialisiert, aber jede nachfolgende Interaktion der Schnittstellenklasse mit der Implementierungsklasse ist auf die Abstraktion beschränkt, die in der Basisimplementierungsklasse unterstützt wird. Der Client interagiert mit der Schnittstellenklasse und „delegiert“ wiederum alle Anforderungen an die Klassenimplementierung.
Das Schnittstellenobjekt ist der vom Client bekannte und verwendete "Handler"; während das Implementierungsobjekt oder der "Körper" sicher gekapselt ist, um sicherzustellen, dass es sich weiterentwickeln oder vollständig ersetzt (oder zur Laufzeit verwendet werden kann.
Verwenden Sie das Brückenmuster, wenn:
- Sie möchten, dass die Implementierung zur Laufzeit bindet
- Sie haben eine Zunahme der Anzahl von Klassen, die sich aus einer gekoppelten Schnittstelle und mehreren Implementierungen ergeben,
- Sie möchten die Implementierung auf mehrere Objekte verteilen,
- Sie müssen orthogonale Klassenhierarchien abbilden.
Zu den Folgen gehören:
- Objektschnittstellenzerlegung
- verbesserte Erweiterbarkeit (Sie können (z. B. Unterklassen) Abstraktions- und Implementierungshierarchien unabhängig voneinander erweitern),
- Ausblenden von Details vor Kunden.
Bridge ist gleichbedeutend mit dem Handler/Body-Idiom. Es ist ein Entwurfsmechanismus, der eine Implementierungsklasse innerhalb einer Schnittstellenklasse kapselt. Der erste ist der Körper und der zweite der Handler. Der Handler wird vom Benutzer als tatsächliche Klasse behandelt, aber die Arbeit wird im Körper erledigt. „Das Handle/Body-Klassen-Idiom kann verwendet werden, um eine komplexe Abstraktion in kleinere, leichter zu handhabende Klassen zu zerlegen. Das Idiom kann die gemeinsame Nutzung einer einzelnen Ressource durch mehrere Klassen widerspiegeln, die den Zugriff darauf kontrollieren (z. B. Referenzzählung)."
Struktur
Der Kunde möchte sich nicht mit plattformabhängigen Details auseinandersetzen. Das Bridge-Muster kapselt diese Komplexität hinter einer abstrakten Hülle.
Bridge betont die Identifizierung und Trennung der Abstraktion „Schnittstelle“ von der Abstraktion „Implementierung“.
Beispiel
Das Brückenmuster trennt die Abstraktion von ihrer Implementierung, sodass sie unabhängig voneinander variieren können. Ein Beispiel für eine Bridge ist ein Haushaltsschalter, der Lichter, Deckenventilatoren usw. steuert. Der Zweck eines Schalters besteht darin, ein Gerät ein- oder auszuschalten. Tatsächlich kann der Schalter als Zugkette, einfacher Ein-/Ausschalter oder verschiedene Dimmerschalter implementiert werden.
Kontrollliste
- Entscheiden Sie, ob es zwei mögliche orthogonale Klassenhierarchien in der Anwendung gibt. Diese unabhängigen Hierarchien können sein: Abstraktion/Plattform oder Domäne/Infrastruktur oder Schnittstelle/Schnittstelle oder Schnittstelle/Implementierung.
- Entwickeln Sie eine Trennung der Anliegen: was der Kunde will und was die Plattformen bieten.
- Erstellen Sie eine Plattformschnittstelle, die minimal, notwendig und ausreichend ist. Sein Zweck ist es, die Abstraktion von der Plattform zu trennen.
- Definieren Sie für jede Plattform eine abgeleitete Klasse dieser Schnittstelle.
- Erstellen Sie eine Basisabstraktionsklasse, die ein „Plattformobjekt“ hat und plattformspezifische Funktionalität an dieses delegiert.
- Definieren Sie bei Bedarf Spezialisierungen für Abstraktionsklassen.
Faustregeln
- Der Adapter ermöglicht es Ihnen, mit Klassen zu arbeiten, nachdem sie entwickelt wurden; Die Brücke sorgt dafür, dass sie funktionieren, bevor sie entworfen wurden.
- Die Brücke wird im Voraus so entworfen, dass sich Abstraktion und Implementierung unabhängig voneinander ändern. Der Adapter modernisiert den Code, sodass die Klassen zusammenarbeiten.
- State, Strategy, Bridge (und teilweise Adapter) haben ähnliche Entscheidungsstrukturen. Sie alle teilen Elemente des Handler/Body-Idioms. Sie unterscheiden sich in ihrer Absicht – das heißt, sie lösen unterschiedliche Probleme.
- Die Struktur von State und Bridge ist identisch (außer dass Bridge Klassenhierarchien zulässt, während State nur eine zulässt). Die beiden Muster verwenden dieselbe Struktur, um unterschiedliche Probleme zu lösen: Zustand ermöglicht es, dass sich das Verhalten eines Objekts zusammen mit seinem Zustand ändert, während die Absicht der Brücke darin besteht, die Abstraktion von ihrer Implementierung zu trennen, sodass sie unabhängig voneinander variieren können.
- Wenn Klassenschnittstellen die Erstellung ihrer Implementierungsklassen delegieren (anstatt sich selbst direkt zu erstellen/zu binden), verwendet das Projekt normalerweise das Abstract-Factory-Muster, um Implementierungen der Objekte zu erstellen.