Was ist das Brückenmuster?
Das Brückenmuster ist ein strukturelles Designmuster. Mit anderen Worten: Seine Hauptaufgabe besteht darin, eine vollständige Struktur aus Klassen und Objekten zu erstellen. Eine Brücke erreicht dies, indem sie eine oder mehrere Klassen in separate Hierarchien unterteilt: Abstraktion und Implementierung . Eine Änderung der Funktionalität in einer Hierarchie zieht keine Änderung in der anderen nach sich. Das ist alles schön und gut, aber diese Definition ist sehr weit gefasst und beantwortet nicht die wichtigste Frage: „Was ist das Brückenmuster?“ Ich denke, es wird für Sie einfacher sein, die praktische Anwendung zu verstehen. Lassen Sie uns also gleich ein klassisches Szenario für das Brückenmuster erstellen. Wir haben eine abstrakteShape
Klasse, die eine generische geometrische Figur darstellt:
-
Shape.java
public abstract class Shape { public abstract void draw(); }
Wenn wir uns entscheiden, Formen wie Dreiecke und Rechtecke hinzuzufügen, sorgen wir dafür, dass sie die
Shape
Klasse erben: -
Rechteck.java:
public class Rectangle extends Shape { @Override public void draw() { System.out.println("Drawing rectangle"); } }
-
Triangle.java:
public class Triangle extends Shape { @Override public void draw() { System.out.println("Drawing triangle"); } }
draw()
Methode hängt von dieser Farbe ab. Um unterschiedliche Implementierungen der draw()
Methode zu erhalten, müssen wir für jede Form-Farb-Kombination eine Klasse erstellen. Wenn wir drei Farben haben, brauchen wir sechs Klassen: TriangleBlack
, TriangleGreen
, TriangleRed
, und . Sechs Unterrichtsstunden sind kein so großes Problem. Aber! Wenn wir eine neue Form oder Farbe hinzufügen müssen, wächst die Anzahl der Klassen exponentiell. Wie kommt man aus dieser Situation heraus? Das Speichern von Farben in einem Feld und das Aufzählen aller Optionen mithilfe von bedingten Anweisungen ist nicht die beste Lösung. Eine gute Lösung besteht darin, die Farbe auf eine separate Schnittstelle zu verschiebenRectangleBlack
RectangleGreen
RectangleRed
. Gesagt, getan: Erstellen wir eine Color
Schnittstelle mit drei Implementierungen: BlackColor
, GreenColor
und RedColor
:
-
Farbe.java:
public interface Color { void fillColor(); }
-
BlackColor.java:
public class BlackColor implements Color { @Override public void fillColor() { System.out.println("Filling in black color"); } }
-
GreenColor.java
public class GreenColor implements Color { @Override public void fillColor() { System.out.println("Filling in green color"); } }
-
RedColor.java
public class RedColor implements Color { @Override public void fillColor() { System.out.println("Filling in red color"); } }
Jetzt fügen wir
Color
derShape
Klasse ein Feld hinzu. Wir erhalten seinen Wert im Konstruktor. -
Shape.java:
public abstract class Shape { protected Color color; public Shape(Color color) { this.color = color; } public abstract void draw(); }
Wir werden die
color
Variable inShape
Implementierungen verwenden. Das bedeutet, dass Shapes nun die Funktionalität derColor
Schnittstelle nutzen können. -
Rechteck.java
public class Rectangle extends Shape { public Rectangle(Color color) { super(color); } @Override public void draw() { System.out.println("Drawing rectangle"); color.fillColor(); } }
Color color
Feld ist eine Brücke, die zwei separate Klassenhierarchien verbindet.
Wie man eine Brücke baut: Abstraktion und Implementierung
Schauen wir uns ein Klassendiagramm an, das das Brückenmuster darstellt: Hier sehen Sie zwei unabhängige Strukturen, die geändert werden können, ohne die Funktionalität der anderen zu beeinträchtigen. In unserem Fall:- Abstraktion ist die
Shape
Klasse - RefinedAbstraction ist die
Triangle
und-Rectangle
Klasse - Implementor ist die
Color
Schnittstelle - ConcreteImplementor sind die Klassen
BlackColor
,GreenColor
und .RedColor
Shape
Klasse ist eine Abstraktion – ein Mechanismus zum Verwalten des Füllens von Formen mit verschiedenen Farben, der an die Color
Schnittstelle (Implementor) delegiert. Die Triangle
und- Rectangle
Klassen sind konkrete Klassen, die den von der Klasse bereitgestellten Mechanismus verwenden Shape
. BlackColor
und GreenColor
sind RedColor
konkrete Implementierungen in der Implementierungshierarchie.
Wo kann das Brückenmuster verwendet werden?
Ein großer Vorteil dieses Musters besteht darin, dass Sie Änderungen an den Funktionsklassen in einer Hierarchie vornehmen können, ohne die Logik der anderen zu zerstören. Außerdem trägt dieser Ansatz dazu bei, die Kopplung zwischen Klassen zu reduzieren. Die wichtigste Voraussetzung bei der Verwendung dieses Musters ist „Befolgen Sie die Anweisungen“ – ignorieren Sie keine davon! Lassen Sie uns zu diesem Zweck die Situationen herausfinden, in denen Sie unbedingt das Brückenmuster verwenden sollten:-
Wenn Sie die Anzahl der Elemente basierend auf Kombinationen zweier Konzepte (z. B. Formen und Farben) erweitern müssen.
-
Wenn Sie eine große Klasse, die nicht dem Prinzip der Einzelverantwortung entspricht, in kleinere Klassen mit eingeschränkter Funktionalität aufteilen möchten.
-
Wenn es notwendig ist, während der Ausführung des Programms Änderungen an der Logik bestimmter Entitäten vorzunehmen.
-
Wenn es notwendig ist, eine Implementierung vor den Clients der Klasse oder Bibliothek zu verbergen.
Vor- und Nachteile des Musters
Wie andere Muster hat eine Brücke sowohl Vor- als auch Nachteile. Vorteile des Brückenmusters:- Es verbessert die Skalierbarkeit des Codes – Sie können Funktionen hinzufügen, ohne befürchten zu müssen, dass etwas in einem anderen Teil des Programms kaputt geht.
- Es reduziert die Anzahl der Unterklassen, wenn die Anzahl der Entitäten andernfalls auf Kombinationen zweier Konzepte (z. B. Formen und Farben) basieren würde.
- Es ermöglicht die getrennte Arbeit an zwei separaten Hierarchien – Abstraktion und Implementierung. Zwei verschiedene Entwickler können Änderungen vornehmen, ohne sich in die Details des Codes des anderen zu vertiefen.
- Es reduziert die Kopplung zwischen Klassen – der einzige Ort, an dem die beiden Klassen gekoppelt sind, ist die Brücke (dh das
Color color
Feld).
- Abhängig von der spezifischen Situation und der Gesamtstruktur eines Projekts kann es sich negativ auf die Leistung eines Programms auswirken (z. B. wenn Sie mehr Objekte initialisieren müssen).
- Dadurch wird der Code schlechter lesbar, da zwischen den beiden Klassen gewechselt werden muss.
GO TO FULL VERSION