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 abstraktShape
klass, 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
, RectangleGreen
och 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 Color
gränssnitt med tre implementeringar: BlackColor
, GreenColor
och 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
Color
fält iShape
klassen. 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
color
variabeln iShape
implementeringar.Color
Det 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:
- Abstraktion är
Shape
klassen - RefinedAbstraction är
Triangle
ochRectangle
klasserna - Implementator är
Color
gränssnittet - ConcreteImplementor är ,
BlackColor
ochGreenColor
klassernaRedColor
.
Shape
är en abstraktion — en mekanism för att hantera fyllningen av former med olika färger, som delegerar till gränssnittet ( Color
Implementor). Klasserna Triangle
och Rectangle
är konkreta klasser som använder den mekanism som gjorts tillgänglig av Shape
klassen. BlackColor
, GreenColor
och 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