CodeGym /Blog Java /Random-PL /Wzorzec projektowy mostu
Autor
Artem Divertitto
Senior Android Developer at United Tech

Wzorzec projektowy mostu

Opublikowano w grupie Random-PL
Cześć! Teraz kontynuujemy zagłębianie się w obszerny i bardzo ważny przydatny temat: wzorce projektowe. Dzisiaj porozmawiajmy o wzorze mostka. Podobnie jak inne wzorce, wzorzec pomostowy służy do rozwiązywania typowych problemów, jakie napotyka programista podczas projektowania architektury oprogramowania. Dzisiaj przestudiujmy cechy tego wzorca i dowiedzmy się, jak go używać.

Jaki jest wzór mostka?

Wzorzec mostka jest strukturalnym wzorcem projektowym. Innymi słowy, jego głównym zadaniem jest stworzenie pełnoprawnej struktury z klas i obiektów. Most robi to, dzieląc jedną lub więcej klas na osobne hierarchie: abstrakcję i implementację . Zmiana funkcjonalności w jednej hierarchii nie pociąga za sobą zmiany w drugiej. Wszystko fajnie, ale ta definicja jest bardzo szeroka i nie odpowiada na najważniejsze pytanie: „Jaki jest wzór mostka?” Myślę, że łatwiej będzie Ci zrozumieć jego praktyczne zastosowanie. Więc od razu stwórzmy klasyczny scenariusz dla wzoru mostka. Mamy Shapeklasę abstrakcyjną, która reprezentuje ogólną figurę geometryczną:
  • kształt.java

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

    Kiedy zdecydujemy się dodać kształty, takie jak trójkąty i prostokąty, sprawimy, że odziedziczą one Shapeklasę:

  • 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");
       }
    }
    
Wszystko wydaje się proste do momentu, gdy wprowadzimy pojęcie koloru. Oznacza to, że każdy kształt będzie miał swój własny kolor, a funkcjonalność metody draw()będzie zależała od tego koloru. Aby mieć różne implementacje metody draw(), musimy utworzyć klasę dla każdej kombinacji kształtu i koloru. Jeśli mamy trzy kolory, potrzebujemy sześciu klas: TriangleBlack, TriangleGreen, TriangleRed, RectangleBlack, RectangleGreeni RectangleRed. Sześć klas to nie taki duży problem. Ale! Jeśli musimy dodać nowy kształt lub kolor, to liczba klas rośnie wykładniczo. Jak wyjść z tej sytuacji? Przechowywanie koloru w polu i wyliczanie wszystkich opcji za pomocą instrukcji warunkowych nie jest najlepszym rozwiązaniem. Dobrym rozwiązaniem jest przeniesienie koloru do osobnego interfejsu. Ledwie powiedziane, to zrobione: stwórzmy Colorinterfejs z trzema implementacjami: BlackColor, GreenColori 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");
       }
    }
    

    Teraz dodajemy Colorpole do Shapeklasy. Otrzymamy jego wartość w konstruktorze.

  • kształt.java:

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

    Zmiennej będziemy używać colorw Shapeimplementacjach. Oznacza to, że kształty mogą teraz korzystać z funkcjonalności interfejsu Color.

  • Rectangle.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! Teraz możemy tworzyć różne kolory i kształty w nieskończoność, a liczba klas będzie rosła tylko liniowo. Pole Color colorjest mostem łączącym dwie oddzielne hierarchie klas.

Jak zbudować most: abstrakcja i implementacja

Spójrzmy na diagram klas, który przedstawia wzorzec pomostu: Wprowadzenie do wzorca projektowania mostów - 2Tutaj możesz zobaczyć dwie niezależne struktury, które można modyfikować bez wpływu na ich funkcjonalność. W naszym przypadku:
  • Abstrakcja to Shapeklasa
  • RefinedAbstraction to klasy TriangleiRectangle
  • Implementator to Colorinterfejs
  • ConcreteImplementor to klasy BlackColor, GreenColori RedColor.
Klasa Shapejest abstrakcją — mechanizmem zarządzającym wypełnianiem kształtów różnymi kolorami, który deleguje do interfejsu Color(Implementora). Klasy Trianglei Rectangleto konkretne klasy, które wykorzystują mechanizm udostępniony przez Shapeklasę. BlackColori GreenColorRedColorkonkretnymi implementacjami w Hierarchii implementacji.

Gdzie używać wzoru mostu

Ogromną zaletą korzystania z tego wzorca jest możliwość wprowadzania zmian w klasach funkcjonalnych w jednej hierarchii bez naruszania logiki drugiej. Takie podejście pomaga również zmniejszyć sprzężenie między klasami. Głównym wymaganiem podczas korzystania z tego wzorca jest „postępuj zgodnie z instrukcjami” — nie ignoruj ​​​​żadnego z nich! W tym celu zastanówmy się, w jakich sytuacjach zdecydowanie powinieneś użyć wzorca mostka:
  1. Jeśli potrzebujesz rozszerzyć liczbę podmiotów w oparciu o kombinacje dwóch pojęć (np. kształty i kolory).

  2. Jeśli chcesz podzielić dużą klasę, która nie spełnia zasady pojedynczej odpowiedzialności na mniejsze klasy, które mają wąską funkcjonalność.

  3. Jeśli konieczne jest dokonanie zmian w logice niektórych podmiotów w trakcie działania programu.

  4. Jeśli konieczne jest ukrycie implementacji przed klientami klasy lub biblioteki.

Kiedy używasz tego wzorca, zawsze pamiętaj, że dodaje on dodatkowe elementy do twojego kodu — użycie go w projekcie, w którym jest tylko jeden kształt i jeden lub dwa możliwe kolory, może nie mieć sensu.

Plusy i minusy wzoru

Podobnie jak inne wzory, most ma zarówno zalety, jak i wady. Zalety wzoru mostka:
  1. Poprawia skalowalność kodu — możesz dodawać funkcjonalności bez obawy, że zepsujesz coś w innej części programu.
  2. Zmniejsza liczbę podklas, gdy w innym przypadku liczba jednostek byłaby oparta na kombinacjach dwóch pojęć (na przykład kształtów i kolorów).
  3. Umożliwia oddzielną pracę na dwóch odrębnych hierarchiach — Abstrakcji i Implementacji. Dwóch różnych programistów może wprowadzać zmiany bez zagłębiania się w szczegóły swojego kodu.
  4. Zmniejsza sprzężenie między klasami — jedynym miejscem, w którym te dwie klasy są sprzężone, jest most (tj. Color colorpole).
Wady wzoru mostka:
  1. W zależności od konkretnej sytuacji i ogólnej struktury projektu może to negatywnie wpłynąć na wydajność programu (na przykład, jeśli trzeba zainicjować więcej obiektów).
  2. Sprawia, że ​​kod jest mniej czytelny ze względu na konieczność przełączania się między dwiema klasami.

Różnica w stosunku do wzorca strategii

Wzorzec mostka jest często mylony z innym wzorcem projektowym — strategią. Oba wykorzystują kompozycję (chociaż w przykładzie użyliśmy agregacji z figurami i kolorami, wzór Bridge może również wykorzystywać kompozycję), delegując pracę innym obiektom. Ale jest między nimi różnica i to ogromna. Wzorzec strategii jest wzorcem behawioralnym: rozwiązuje zupełnie inne problemy. Strategia umożliwia wymianę algorytmów, podczas gdy most oddziela abstrakcję od implementacji, aby wybierać między różnymi implementacjami. Innymi słowy, w przeciwieństwie do strategii, pomost dotyczy całych jednostek lub struktur hierarchicznych. Wzór mostka może być dobrą bronią w arsenale programisty. Najważniejsze jest zidentyfikowanie sytuacji, w których warto go użyć i rozpoznanie, kiedy odpowiedni jest inny wzorzec.
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION