Vad är bromönstret?
Bromönstret är ett strukturellt designmönster. Med andra ord är dess huvudsakliga uppgift att skapa en fullfjädrad struktur av klasser och objekt. En brygga gör detta genom att dela upp en eller flera klasser i separata hierarkier: abstraktion och implementering . En förändring av funktionalitet i den ena hierarkin innebär inte en förändring i den andra. Det är bra och bra, men denna definition är väldigt bred och svarar inte på den viktigaste frågan: "Vad är bromönstret?" Jag tror att det blir lättare för dig att förstå dess praktiska tillämpning. Så direkt, låt oss skapa ett klassiskt scenario för bromönstret. Vi har en abstraktShapeklass, som representerar en generisk geometrisk figur:
-
Shape.java
public abstract class Shape { public abstract void draw(); }När vi bestämmer oss för att lägga till former som trianglar och rektanglar kommer vi att få dem att ärva klassen
Shape: -
Rectangle.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()kommer att bero på denna färg. För att ha olika implementeringar av draw()metoden måste vi skapa en klass för varje form-färgkombination. Om vi har tre färger behöver vi sex klasser: TriangleBlack, TriangleGreen, TriangleRed, RectangleBlack, RectangleGreenoch RectangleRed. Sex klasser är inte ett så stort problem. Men! Om vi behöver lägga till en ny form eller färg, så växer antalet klasser exponentiellt. Hur tar man sig ur denna situation? Att lagra färg i ett fält och räkna upp alla alternativ med villkorliga uttalanden är inte den bästa lösningen. En bra lösning är att flytta färg till ett separat gränssnitt. Inte tidigare sagt än gjort: låt oss skapa ett Colorgränssnitt med tre implementeringar: BlackColor, GreenColoroch RedColor:
-
Color.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 lägger vi till ett
Colorfält iShapeklassen. Vi får dess värde i konstruktören. -
Shape.java:
public abstract class Shape { protected Color color; public Shape(Color color) { this.color = color; } public abstract void draw(); }Vi kommer att använda
colorvariabeln iShapeimplementeringar.ColorDet betyder att former nu kan använda gränssnittets funktionalitet . -
Rectangle.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är en bro som förbinder två separata klasshierarkier.
Hur man bygger en bro: abstraktion och implementering
Låt oss titta på ett klassdiagram som skildrar bromönstret:
Här kan du se två oberoende strukturer som kan modifieras utan att påverka varandras funktionalitet. I vårat fall:
- Abstraktion är
Shapeklassen - RefinedAbstraction är
TriangleochRectangleklasserna - Implementator är
Colorgränssnittet - ConcreteImplementor är ,
BlackColorochGreenColorklassernaRedColor.
Shapeär en abstraktion — en mekanism för att hantera fyllningen av former med olika färger, som delegerar till gränssnittet ( ColorImplementor). Klasserna Triangleoch Rectangleär konkreta klasser som använder den mekanism som gjorts tillgänglig av Shapeklassen. BlackColor, GreenColoroch RedColorär konkreta implementeringar i implementeringshierarkin.
Var man använder bromönstret
En stor fördel med att använda detta mönster är att du kan göra ändringar i funktionsklasserna i en hierarki utan att bryta logiken i den andra. Detta tillvägagångssätt hjälper också till att minska kopplingen mellan klasser. Huvudkravet när du använder det här mönstret är "följ instruktionerna" - ignorera inte någon av dem! För det ändamålet, låt oss ta reda på situationerna när du definitivt bör använda bromönstret:-
Om du behöver utöka antalet enheter baserat på kombinationer av två begrepp (t.ex. former och färger).
-
Om man vill dela upp en stor klass som inte uppfyller enansvarsprincipen i mindre klasser som har snäv funktionalitet.
-
Om det är nödvändigt att göra ändringar i logiken för vissa enheter medan programmet körs.
-
Om det är nödvändigt att dölja en implementering för klassens eller bibliotekets klienter.
För- och nackdelar med mönstret
Liksom andra mönster har en bro både fördelar och nackdelar. Fördelar med bromönstret:- Det förbättrar skalbarheten för koden - du kan lägga till funktionalitet utan rädsla för att gå sönder något i en annan del av programmet.
- Det minskar antalet underklasser när antalet entiteter annars skulle baseras på kombinationer av två begrepp (till exempel former och färger).
- Det gör det möjligt att separat arbeta på två separata hierarkier — Abstraktion och Implementering. Två olika utvecklare kan göra ändringar utan att fördjupa sig i detaljerna i varandras kod.
- Det minskar kopplingen mellan klasser — den enda platsen där de två klasserna är kopplade är bron (dvs. fältet)
Color color.
- Beroende på den specifika situationen och den övergripande strukturen för ett projekt kan det påverka ett programs prestanda negativt (till exempel om du behöver initiera fler objekt).
- Det gör koden mindre läsbar på grund av behovet av att växla mellan de två klasserna.
GO TO FULL VERSION