Jaki jest wzór mostu?
Wzorzec Most jest wzorcem konstrukcyjnym. Oznacza to, że jego głównym zadaniem jest utworzenie kompletnej struktury klas i obiektów. Bridge rozwiązuje ten problem, rozdzielając jedną lub więcej klas na osobne hierarchie – abstrakcja i implementacja . Zmiana funkcjonalności w jednej hierarchii nie pociąga za sobą zmian w innej. Wszystko wydaje się jasne, ale w rzeczywistości definicja ta brzmi bardzo szeroko i nie odpowiada na główne pytanie: „Co to jest wzór Bridge?” Myślę, że łatwiej będzie Ci to sprawdzić w praktyce. Zamodelujmy od razu klasyczny przykład wzoru Bridge. Mamy klasę abstrakcyjnąShape
, która ogólnie opisuje figurę geometryczną:
-
Kształt.java
public abstract class Shape { public abstract void draw(); }
Kiedy zdecydujemy się na dodanie kształtów trójkąta i prostokąta, będziemy dziedziczyć po klasie
Shape
: -
Prostokąt.java:
public class Rectangle extends Shape { @Override public void draw() { System.out.println("Drawing rectangle"); } }
-
Trójkąt.java:
public class Triangle extends Shape { @Override public void draw() { System.out.println("Drawing triangle"); } }
draw()
. Aby mieć różne implementacje metody draw()
, musimy stworzyć klasę dla każdego kształtu odpowiadającego kolorowi. Jeśli są trzy kolory, to istnieje sześć klas: TriangleBlack
, TriangleGreen
, TriangleRed
, i . Sześć klas to nie jest aż tak dużo. Ale! Jeśli będziemy musieli dodać nowy kształt lub kolor, liczba klas będzie rosła wykładniczo. Jak wyjść z tej sytuacji? Przechowywanie kolorów w polu i wypróbowywanie opcji za pomocą warunków warunkowych nie jest najlepszym rozwiązaniem. Dobrym rozwiązaniem jest wyświetlanie kolorów w osobnym interfejsie . Zaraz powiedziane, niż zrobione: stwórzmy interfejs i trzy jego implementacje - , oraz : RectangleBlack
RectangleGreen
RectangleRed
Color
BlackColor
GreenColor
RedColor
-
Kolor.java:
public interface Color { void fillColor(); }
-
CzarnyKolor.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"); } }
Dodajmy teraz
Color
do klasy pole typuShape
- jego wartość otrzymamy w konstruktorze. -
Kształt.java:
public abstract class Shape { protected Color color; public Shape(Color color) { this.color = color; } public abstract void draw(); }
color
Będziemy używać tej zmiennej w implementacjachShape
. Oznacza to, że kształty mogą teraz korzystać z funkcjonalności interfejsuColor
. -
Prostokąt.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
jest pomostem łączącym dwie oddzielne hierarchie klas.
Urządzenie pomostowe: czym jest abstrakcja i implementacja
Przyjrzyjmy się diagramowi klas opisującemu wzorzec Bridge: Tutaj widać dwie niezależne struktury, które można modyfikować bez wpływu na swoją funkcjonalność. W naszym przypadku jest to:- Abstrakcja - zajęcia
Shape
; - RefinedAbstraction -class
Triangle
,;Rectangle
- Implementator - interfejs
Color
; - ConcreteImplementor - klasy
BlackColor
iGreenColor
.RedColor
Shape
reprezentuje Abstrakcję - mechanizm kontrolowania kolorowania kształtów w różnych kolorach, który deleguje Implementację do interfejsu Color
. Klasy Triangle
to Rectangle
rzeczywiste obiekty korzystające z mechanizmu oferowanego przez klasę Shape
. BlackColor
oraz GreenColor
- RedColor
konkretne wdrożenia w branży Wdrożenia. Często nazywane są platformą.
Gdzie używany jest wzór Bridge?
Ogromną zaletą stosowania tego wzorca jest to, że można wprowadzać zmiany w funkcjonalności klas w jednej gałęzi bez naruszania logiki innej. Takie podejście pomaga również zmniejszyć łączenie klas programu. Głównym warunkiem korzystania z wzorów jest „stosowanie się do instrukcji”: nie przyklejaj ich nigdzie! Właściwie zastanówmy się, w jakich przypadkach zdecydowanie musisz użyć Bridge:-
Jeśli konieczne jest rozszerzenie liczby elementów w dwóch kierunkach (kształty geometryczne, kolory).
-
Jeśli chcesz podzielić dużą klasę, która nie spełnia zasady pojedynczej odpowiedzialności, na mniejsze klasy o wąskiej funkcjonalności.
-
Jeżeli zaistnieje ewentualna potrzeba wprowadzenia zmian w logice działania poszczególnych podmiotów w trakcie działania programu.
-
Jeśli to konieczne, ukryj implementację przed klientami klasy (biblioteki).
Plusy i minusy wzoru
Podobnie jak inne wzory, Most ma zarówno zalety, jak i wady. Korzyści z mostu:- Poprawia skalowalność kodu - możesz dodawać funkcjonalności bez obawy, że coś zepsujesz w innej części programu.
- Zmniejsza liczbę podklas - sprawdza się, gdy zachodzi potrzeba rozszerzenia liczby bytów w dwóch kierunkach (np. liczba kształtów i liczba kolorów).
- Umożliwia odrębną pracę na dwóch niezależnych gałęziach Abstrakcji i Implementacji - może to zrobić dwóch różnych programistów, bez zagłębiania się w szczegóły kodu drugiego.
- Ograniczenie łączenia klas - jedynym miejscem łączenia dwóch klas jest most (pole
Color color
).
- W zależności od konkretnej sytuacji i struktury projektu jako całości, może to mieć negatywny wpływ na produktywność programu (na przykład, jeśli trzeba zainicjować więcej obiektów).
- Komplikuje czytelność kodu ze względu na konieczność poruszania się pomiędzy klasami.
GO TO FULL VERSION