CodeGym /Java-Blog /Random-DE /Brückenentwurfsmuster
Autor
Artem Divertitto
Senior Android Developer at United Tech

Brückenentwurfsmuster

Veröffentlicht in der Gruppe Random-DE
Hallo! Wir befassen uns nun weiter mit einem umfangreichen und überaus wichtigen nützlichen Thema: Designmuster. Lassen Sie uns heute über das Brückenmuster sprechen. Wie andere Muster dient das Brückenmuster dazu, typische Probleme zu lösen, auf die ein Entwickler beim Entwurf einer Softwarearchitektur stößt. Lassen Sie uns heute die Funktionen dieses Musters untersuchen und herausfinden, wie man es verwendet.

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 abstrakte ShapeKlasse, 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 ShapeKlasse 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");
       }
    }
    
Alles sieht einfach aus, bis wir das Konzept der Farbe vorstellen. Das heißt, jede Form hat ihre eigene Farbe und die Funktionalität der 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 verschiebenRectangleBlackRectangleGreenRectangleRed. Gesagt, getan: Erstellen wir eine ColorSchnittstelle mit drei Implementierungen: BlackColor, GreenColorund 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 Colorder ShapeKlasse 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 colorVariable in ShapeImplementierungen verwenden. Das bedeutet, dass Shapes nun die Funktionalität der ColorSchnittstelle 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();
       }
    }
    
Ta-da! Jetzt können wir unendlich viele verschiedene Farben und Formen erstellen, und die Anzahl der Klassen wird nur linear zunehmen. Das Color colorFeld 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: Einführung in das Brückenentwurfsmuster – 2Hier 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 ShapeKlasse
  • RefinedAbstraction ist die Triangleund- RectangleKlasse
  • Implementor ist die ColorSchnittstelle
  • ConcreteImplementor sind die Klassen BlackColor, GreenColorund .RedColor
Die ShapeKlasse ist eine Abstraktion – ein Mechanismus zum Verwalten des Füllens von Formen mit verschiedenen Farben, der an die ColorSchnittstelle (Implementor) delegiert. Die Triangleund- RectangleKlassen sind konkrete Klassen, die den von der Klasse bereitgestellten Mechanismus verwenden Shape. BlackColorund GreenColorsind RedColorkonkrete 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:
  1. Wenn Sie die Anzahl der Elemente basierend auf Kombinationen zweier Konzepte (z. B. Formen und Farben) erweitern müssen.

  2. Wenn Sie eine große Klasse, die nicht dem Prinzip der Einzelverantwortung entspricht, in kleinere Klassen mit eingeschränkter Funktionalität aufteilen möchten.

  3. Wenn es notwendig ist, während der Ausführung des Programms Änderungen an der Logik bestimmter Entitäten vorzunehmen.

  4. Wenn es notwendig ist, eine Implementierung vor den Clients der Klasse oder Bibliothek zu verbergen.

Wenn Sie dieses Muster verwenden, denken Sie immer daran, dass es Ihrem Code zusätzliche Entitäten hinzufügt – es ist möglicherweise nicht sinnvoll, es in einem Projekt zu verwenden, in dem es nur eine Form und eine oder zwei mögliche Farben gibt.

Vor- und Nachteile des Musters

Wie andere Muster hat eine Brücke sowohl Vor- als auch Nachteile. Vorteile des Brückenmusters:
  1. 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.
  2. 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.
  3. 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.
  4. Es reduziert die Kopplung zwischen Klassen – der einzige Ort, an dem die beiden Klassen gekoppelt sind, ist die Brücke (dh das Color colorFeld).
Nachteile des Brückenmusters:
  1. 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).
  2. Dadurch wird der Code schlechter lesbar, da zwischen den beiden Klassen gewechselt werden muss.

Unterschied zum Strategiemuster

Das Brückenmuster wird oft mit einem anderen Entwurfsmuster verwechselt – der Strategie. Beide verwenden Komposition (obwohl wir im Beispiel die Aggregation mit Figuren und Farben verwendet haben, kann das Brückenmuster auch Komposition verwenden) und die Arbeit an andere Objekte delegieren. Aber es gibt einen Unterschied zwischen ihnen, und er ist riesig. Das Strategiemuster ist ein Verhaltensmuster: Es löst ganz andere Probleme. Die Strategie ermöglicht den Austausch von Algorithmen, während Bridge eine Abstraktion von Implementierungen trennt, um zwischen verschiedenen Implementierungen wählen zu können. Mit anderen Worten: Im Gegensatz zu einer Strategie gilt eine Brücke für ganze Einheiten oder hierarchische Strukturen. Das Brückenmuster kann eine gute Waffe im Arsenal eines Entwicklers sein. Die Hauptsache besteht darin, die Situationen zu identifizieren, in denen es sich lohnt, es einzusetzen, und zu erkennen, wann ein anderes Muster angemessen ist.
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION