- Brücke (Entwurfsmuster)
-
Eine Brücke (engl. Bridge) ist in der Softwareentwicklung ein Entwurfsmuster und gehört zur Kategorie der Strukturmuster (Structural Patterns). Das Muster dient zur Trennung der Implementierung von ihrer Abstraktion (Schnittstelle), wodurch beide unabhängig voneinander verändert werden können. Es ist ein Entwurfsmuster der sogenannten GoF-Muster (siehe Viererbande).
Inhaltsverzeichnis
Problem
Normalerweise wird eine Implementierung durch Vererbung der Abstraktion realisiert. Dies kann jedoch dazu führen, dass in der Vererbungshierarchie sowohl Implementierungen als auch andere abstrakte Klassen zu finden sind. Dies macht die Vererbungshierarchie unübersichtlich und schwer zu warten.
Lösung
Werden die abstrakten Klassen und die Implementierungen in zwei verschiedenen Hierarchien verwaltet, so gewinnt erstens die Übersichtlichkeit und zweitens wird die Anwendung unabhängig von der Implementierung.
Allgemeine Verwendung
Eine Brücke findet Anwendung, wenn sowohl Abstraktion als auch Implementierung erweiterbar sein sollen und eine dauerhafte Verbindung zwischen Abstraktion und Implementierung verhindert werden soll. Weiterhin wird sie angewandt, wenn Änderungen der Implementierung ohne Auswirkungen für den Klienten sein sollen, die Implementierung vor dem Klienten verborgen bleiben soll oder die Implementierung von verschiedenen Klassen gleichzeitig genutzt werden soll.
UML-Diagramm
Akteure
Die Abstraktion (im Beispiel: List) definiert einerseits die Schnittstelle der Abstraktion, andererseits hält sie eine Referenz zu einem Implementierer. Die SpezAbstraktion (im Beispiel: SortedList) erweitert die Schnittstelle. Der Implementierer (im Beispiel: ListImpl) definiert die Schnittstelle der Implementierung. Er kann sich dabei von Schnittstelle der Abstraktion erheblich unterscheiden. Der KonkrImplementierer (im Beispiel: ArrayList) enthält eine konkrete Implementierung durch Implementierung der Schnittstelle.
Vorteile
Die Vorteile einer Brücke bestehen darin, dass Abstraktion und Implementierung entkoppelt werden. Die Implementierung ist weiterhin während der Laufzeit dynamisch änderbar und die Erweiterbarkeit von Abstraktion und Implementierung wird verbessert.
Durch Angabe eines Parameters bei der Erzeugung einer Abstraktion kann die Implementierung gewählt werden, zudem wird die Implementierung für den Klienten vollständig versteckt. Eine starke Vergrößerung der Anzahl der Klassen kann vermieden werden.
Code-Beispiele
Ruby
class Abstraction def initialize(implementor) @implementor = implementor end def operation raise 'Implementor-Objekt antwortet nicht auf die operation-Methode' unless @implementor.respond_to?(:operation) @implementor.operation end end class RefinedAbstraction < Abstraction def operation puts 'Starte Vorgang...' super end end class Implementor def operation puts 'Wichtige Schritte ausführen' end end class ConcreteImplementorA < Implementor def operation super puts 'Zusätzliche Schritte ausführen' end end class ConcreteImplementorB < Implementor def operation super puts 'Andere, zusätzliche Schritte ausführen' end end normal_with_a = Abstraction.new(ConcreteImplementorA.new) normal_with_a.operation # Wichtige Schritte ausführen # Zusätzliche Schritte ausführen normal_with_b = Abstraction.new(ConcreteImplementorB.new) normal_with_b.operation # Wichtige Schritte ausführen # Andere, zusätzliche Schritte ausführen refined_with_a = RefinedAbstraction.new(ConcreteImplementorA.new) refined_with_a.operation # Starte Vorgang... # Wichtige Schritte ausführen # Zusätzliche Schritte ausführen refined_with_b = RefinedAbstraction.new(ConcreteImplementorB.new) refined_with_b.operation # Starte Vorgang... # Wichtige Schritte ausführen # Andere, zusätzliche Schritte ausführen
Verwandte Entwurfsmuster
Zum Erzeugen der des Implementierungsobjekts der Brücke kann eine Abstrakte Fabrik verwendet werden.
Ein Adapter ist der Brücke scheinbar ähnlich. Jedoch dient der Adapter einer nachträglichen Anpassung einer Klasse an eine Schnittstelle, während die Brücke eine gezielte Entscheidung zur Entkopplung ist. Beide Entwurfsmuster sind also gegensätzlich, können aber in ihrer Implementierung sehr ähnlich aussehen.
Erzeugungsmuster: Abstrakte Fabrik | Singleton | Builder | Fabrikmethode | Prototyp
Strukturmuster: Adapter | Brücke | Decorator | Fassade | Flyweight | Kompositum | Stellvertreter
Verhaltensmuster: Observer | Visitor | Interpreter | Iterator | Kommando | Memento | Schablonenmethode | Strategie | Vermittler | Zustand | Zuständigkeitskette
(Klassenmuster sind kursiv dargestellt)
Wikimedia Foundation.