CodeGym /Java Blog /Willekeurig /Brug ontwerppatroon
John Squirrels
Niveau 41
San Francisco

Brug ontwerppatroon

Gepubliceerd in de groep Willekeurig
Hoi! We verdiepen ons nu verder in een uitgebreid en super belangrijk bruikbaar onderwerp: design patterns. Laten we het vandaag hebben over het brugpatroon. Net als andere patronen dient het brugpatroon om typische problemen op te lossen die een ontwikkelaar tegenkomt bij het ontwerpen van softwarearchitectuur. Laten we vandaag de kenmerken van dit patroon bestuderen en ontdekken hoe we het kunnen gebruiken.

Wat is het brugpatroon?

Het brugpatroon is een structureel ontwerppatroon. Met andere woorden, zijn belangrijkste taak is het creëren van een volwaardige structuur uit klassen en objecten. Een bridge doet dit door een of meer klassen op te delen in afzonderlijke hiërarchieën: abstractie en implementatie . Een verandering in functionaliteit in de ene hiërarchie brengt geen verandering in de andere met zich mee. Dat is allemaal leuk en aardig, maar deze definitie is erg breed en geeft geen antwoord op de belangrijkste vraag: "Wat is het brugpatroon?" Ik denk dat het voor u gemakkelijker zal zijn om de praktische toepassing ervan te begrijpen. Laten we dus meteen een klassiek scenario maken voor het brugpatroon. We hebben een abstracte Shapeklasse, die een generieke geometrische figuur vertegenwoordigt:
  • Vorm.java

    
    public abstract class Shape {
       public abstract void draw();
    }
    

    Wanneer we besluiten om vormen zoals driehoeken en rechthoeken toe te voegen, laten we ze de Shapeklasse erven:

  • Rechthoek.java:

    
    public class Rectangle extends Shape {
       @Override
       public void draw() {
           System.out.println("Drawing rectangle");
       }
    }
    
  • Driehoek.java:

    
    public class Triangle extends Shape {
       @Override
       public void draw() {
           System.out.println("Drawing triangle");
       }
    }
    
Alles ziet er eenvoudig uit tot het moment dat we het concept kleur introduceren. Dat wil zeggen, elke vorm heeft zijn eigen kleur en de functionaliteit van de draw()methode hangt af van deze kleur. Om verschillende implementaties van de draw()methode te hebben, moeten we een klasse maken voor elke vorm-kleurcombinatie. Als we drie kleuren hebben, hebben we zes klassen nodig: TriangleBlack, TriangleGreen, TriangleRed, RectangleBlack, RectangleGreenen RectangleRed. Zes klassen is niet zo'n groot probleem. Maar! Als we een nieuwe vorm of kleur moeten toevoegen, groeit het aantal klassen exponentieel. Hoe kom je uit deze situatie? Kleur opslaan in een veld en alle opties opsommen met behulp van voorwaardelijke instructies is niet de beste oplossing. Een goede oplossing is om kleur naar een aparte interface te verplaatsen. Zo gezegd, zo gedaan: laten we een Colorinterface maken met drie implementaties: BlackColor, GreenColoren RedColor:
  • Kleur.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");
       }
    }
    

    Nu voegen we een Colorveld toe aan de Shapeklasse. We krijgen de waarde ervan in de constructor.

  • Vorm.java:

    
    public abstract class Shape {
       protected Color color;
      
       public Shape(Color color) {
           this.color = color;
       }
    
       public abstract void draw();
    }
    

    We zullen de colorvariabele gebruiken in Shapeimplementaties. Dit betekent dat vormen nu de functionaliteit van de interface kunnen gebruiken Color.

  • Rechthoek.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! Nu kunnen we tot in het oneindige verschillende kleuren en vormen maken, en het aantal klassen zal alleen lineair toenemen. Het Color colorveld is een brug die twee afzonderlijke klassenhiërarchieën met elkaar verbindt.

Hoe een brug te bouwen: abstractie en implementatie

Laten we eens kijken naar een klassendiagram dat het brugpatroon weergeeft: Introductie van het brugontwerppatroon - 2Hier zie je twee onafhankelijke structuren die kunnen worden gewijzigd zonder elkaars functionaliteit te beïnvloeden. In ons geval:
  • Abstractie is de Shapeklasse
  • RefinedAbstraction is de klasse TriangleenRectangle
  • Uitvoerder is de Colorinterface
  • ConcreteImplementor is de klasse BlackColor, GreenColoren RedColor.
De Shapeklasse is een abstractie — een mechanisme voor het beheer van het vullen van vormen met verschillende kleuren, dat wordt gedelegeerd aan de Colorinterface (Implementor). De klassen Triangleen Rectanglezijn concrete klassen die gebruikmaken van het mechanisme dat door de Shapeklasse beschikbaar wordt gesteld. BlackColor, GreenColoren RedColorzijn concrete implementaties in de Implementatiehiërarchie.

Waar het brugpatroon te gebruiken

Een groot voordeel van het gebruik van dit patroon is dat u wijzigingen kunt aanbrengen in de functionele klassen in de ene hiërarchie zonder de logica van de andere te doorbreken. Deze aanpak helpt ook om de koppeling tussen klassen te verminderen. De belangrijkste vereiste bij het gebruik van dit patroon is "volg de instructies" - negeer ze niet! Laten we daarom de situaties uitzoeken waarin u zeker het brugpatroon moet gebruiken:
  1. Als u het aantal entiteiten wilt uitbreiden op basis van combinaties van twee concepten (bijvoorbeeld vormen en kleuren).

  2. Als u een grote klasse die niet voldoet aan het principe van één verantwoordelijkheid wilt verdelen in kleinere klassen met beperkte functionaliteit.

  3. Als het nodig is om wijzigingen aan te brengen in de logica van bepaalde entiteiten terwijl het programma draait.

  4. Als het nodig is om een ​​implementatie te verbergen voor de clients van de klas of bibliotheek.

Wanneer u dit patroon gebruikt, onthoud dan altijd dat het extra entiteiten toevoegt aan uw code - het is misschien niet logisch om het te gebruiken in een project waar er maar één vorm en één of twee mogelijke kleuren zijn.

Voors en tegens van het patroon

Net als andere patronen heeft een brug zowel voor- als nadelen. Voordelen van het brugpatroon:
  1. Het verbetert de schaalbaarheid van code - u kunt functionaliteit toevoegen zonder bang te hoeven zijn iets in een ander deel van het programma kapot te maken.
  2. Het vermindert het aantal subklassen wanneer het aantal entiteiten anders gebaseerd zou zijn op combinaties van twee concepten (bijvoorbeeld vormen en kleuren).
  3. Het maakt het mogelijk om afzonderlijk aan twee afzonderlijke hiërarchieën te werken: abstractie en implementatie. Twee verschillende ontwikkelaars kunnen wijzigingen aanbrengen zonder zich te verdiepen in de details van elkaars code.
  4. Het vermindert de koppeling tussen klassen — de enige plaats waar de twee klassen zijn gekoppeld is de brug (dwz het Color colorveld).
Nadelen van het brugpatroon:
  1. Afhankelijk van de specifieke situatie en de algehele structuur van een project, kan dit een negatieve invloed hebben op de prestaties van een programma (bijvoorbeeld als u meer objecten moet initialiseren).
  2. Het maakt code minder leesbaar vanwege de noodzaak om tussen de twee klassen te schakelen.

Verschil met het strategiepatroon

Het brugpatroon wordt vaak verward met een ander ontwerppatroon: strategie. Ze gebruiken allebei compositie (hoewel we in het voorbeeld aggregatie gebruikten met figuren en kleuren, kan het Bridge-patroon ook compositie gebruiken), waarbij werk aan andere objecten wordt gedelegeerd. Maar er is een verschil tussen hen, en het is enorm. Het strategiepatroon is een gedragspatroon: het lost totaal andere problemen op. Strategie maakt het mogelijk om algoritmen uit te wisselen, terwijl bridge een abstractie scheidt van implementaties om te kunnen kiezen tussen verschillende implementaties. Met andere woorden, in tegenstelling tot een strategie, is een brug van toepassing op hele entiteiten of hiërarchische structuren. Het brugpatroon kan een goed wapen zijn in het arsenaal van een ontwikkelaar. Het belangrijkste is om de situaties te identificeren waarin het de moeite waard is om het te gebruiken en te herkennen wanneer een ander patroon geschikt is.
Opmerkingen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION