Czy ktoś kiedykolwiek używał wzorca mostu w prawdziwej aplikacji? Jeśli tak, jak z tego korzystałeś? Czy to ja, czy jest to tylko wzorzec adaptera z niewielkim zastrzykiem zależności wrzuconym do miksu? Czy naprawdę zasługuje na swój własny wzór?
design-patterns
adapter
bridge
Charles Graham
źródło
źródło
Odpowiedzi:
Klasyczny przykład wzorca Bridge jest używany w definicji kształtów w środowisku interfejsu użytkownika (patrz wpis w Wikipedii dotyczący wzorca mostu ). Wzór Bridge jest kompozyt z szablonu i strategii desenie.
Niektóre aspekty wzorca adaptera we wzorcu mostka są typowym widokiem. Jednak cytując z tego artykułu :
źródło
Jest połączenie odpowiedzi Federico i Johna .
Kiedy:
Refaktoryzuj na:
źródło
Wzorzec Bridge jest zastosowaniem starej rady „przedkładaj kompozycję nad dziedziczenie”. Jest to przydatne, gdy musisz podklasować różne czasy w sposób ortogonalny względem siebie. Powiedzmy, że musisz wdrożyć hierarchię kolorowych kształtów. Nie utworzyłbyś podklasy Shape z Rectangle i Circle, a następnie podklasy Rectangle z RedRectangle, BlueRectangle i GreenRectangle i tak samo dla Circle, prawda? Wolałbyś powiedzieć, że każdy Shape ma kolor i zastosować hierarchię kolorów, a to jest wzór mostu. Cóż, nie wprowadziłbym „hierarchii kolorów”, ale masz pomysł ...
źródło
Kiedy:
Refaktoryzuj na:
źródło
Adapter i mostek są z pewnością powiązane, a różnica jest subtelna. Jest prawdopodobne, że niektórzy ludzie, którzy myślą, że używają jednego z tych wzorców, w rzeczywistości używają drugiego.
Wyjaśnienie, które widziałem, jest takie, że Adapter jest używany, gdy próbujesz ujednolicić interfejsy niektórych niezgodnych klas, które już istnieją . Adapter działa jako rodzaj translatora implementacji, które można uznać za starsze .
Podczas gdy wzorzec Bridge jest używany dla kodu, który z większym prawdopodobieństwem będzie typu greenfield. Projektujesz Bridge, aby zapewnić abstrakcyjny interfejs dla implementacji, która musi się różnić, ale także definiujesz interfejs tych klas implementacji.
Sterowniki urządzeń są często cytowanym przykładem Bridge, ale powiedziałbym, że jest to Bridge, jeśli definiujesz specyfikację interfejsu dla dostawców urządzeń, ale jest to adapter, jeśli bierzesz istniejące sterowniki urządzeń i tworzysz klasę opakowania do zapewniają ujednolicony interfejs.
Więc pod względem kodu te dwa wzorce są bardzo podobne. Pod względem biznesowym są różne.
Zobacz także http://c2.com/cgi/wiki?BridgePattern
źródło
Z mojego doświadczenia wynika, że Bridge jest dość często powtarzającym się wzorcem, ponieważ jest rozwiązaniem, gdy w domenie występują dwa ortogonalne wymiary . Np. Kształty i metody rysowania, zachowania i platformy, formaty plików i serializatory i tak dalej.
I rada: zawsze myśl o wzorcach projektowych z perspektywy koncepcyjnej , a nie implementacyjnej. Z właściwego punktu widzenia Bridge nie można pomylić z adapterem, ponieważ rozwiązują inny problem, a kompozycja jest lepsza od dziedziczenia nie ze względu na samą siebie, ale dlatego, że pozwala osobno zająć się kwestiami ortogonalnymi.
źródło
Przeznaczenie Bridge i Adapter jest inne i potrzebujemy obu wzorców osobno.
Wzór mostka:
Użyj wzorca Bridge, gdy:
@ John Sonmez odpowiedź jasno pokazuje skuteczność wzorca mostu w redukcji hierarchii klas.
Możesz zapoznać się z poniższym linkiem do dokumentacji, aby uzyskać lepszy wgląd we wzorzec mostu z przykładem kodu
Wzór adaptera :
Kluczowe różnice:
Powiązane pytanie SE z diagramem UML i działającym kodem:
Różnica między wzorem mostka a wzorem adaptera
Przydatne artykuły:
artykuł o wzorach mostów źródłowych
artykuł wzór adaptera do produkcji źródła
artykuł o wzorach mostów Journaldev
EDYTOWAĆ:
Przykładowy wzorzec mostu w świecie rzeczywistym (zgodnie z sugestią meta.stackoverflow.com, przykład witryny z dokumentacją uwzględnioną w tym poście, ponieważ dokumentacja zostanie zachowana)
Wzorzec mostu oddziela abstrakcję od implementacji, dzięki czemu oba mogą się zmieniać niezależnie. Osiągnięto to raczej dzięki kompozycji niż dziedziczeniu.
Wzorzec mostkowy UML z Wikipedii:
W tym wzorze masz cztery komponenty.
Abstraction
: Definiuje interfejsRefinedAbstraction
: Implementuje abstrakcję:Implementor
: Definiuje interfejs do implementacjiConcreteImplementor
: Implementuje interfejs implementatora.The crux of Bridge pattern :
Dwie ortogonalne hierarchie klas wykorzystujące kompozycję (bez dziedziczenia). Hierarchia abstrakcji i hierarchia implementacji mogą się zmieniać niezależnie. Implementacja nigdy nie odnosi się do abstrakcji. Abstrakcja zawiera interfejs implementacji jako element członkowski (poprzez kompozycję). Ta kompozycja redukuje o jeden poziom hierarchii dziedziczenia.Prawdziwe słowo Zastosowanie:
Włącz różne pojazdy, aby mieć obie wersje ręcznego i automatycznego systemu zmiany biegów.
Przykładowy kod:
wynik:
Wyjaśnienie:
Vehicle
jest abstrakcją.Car
iTruck
są dwiema konkretnymi implementacjamiVehicle
.Vehicle
definiuje metody abstrakcyjne:addGear()
.Gear
jest interfejsem implementatoraManualGear
iAutoGear
są dwiema implementacjamiGear
Vehicle
zawieraimplementor
interfejs, a nie implementuje interfejs.Compositon
interfejsu implementatora jest sednem tego wzorca: pozwala na niezależne zróżnicowanie abstrakcji i implementacji.Car
iTruck
zdefiniuj implementację (przedefiniowaną abstrakcję) dla abstrakcji::addGear()
ZawieraGear
- AlboManual
alboAuto
Przypadki użycia dla wzorca mostka :
źródło
W pracy używałem wzoru mostka. Programuję w C ++, gdzie często nazywany jest idiomem PIMPL (wskaźnik implementacji). To wygląda tak:
W tym przykładzie
class A
zawiera interfejs iclass Aimpl
zawiera implementację.Jednym z zastosowań tego wzorca jest ujawnienie tylko niektórych publicznych członków klasy implementacji, ale innych nie. W tym przykładzie
Aimpl::foo()
można wywołać tylko za pośrednictwem publicznego interfejsu programuA
, ale nieAimpl::bar()
Kolejną zaletą jest to, że możesz zdefiniować
Aimpl
w oddzielnym pliku nagłówkowym, który nie musi być dołączany przez użytkownikówA
. Wszystko, co musisz zrobić, to użyć deklaracji forwardAimpl
przedA
zdefiniowaniem i przenieść definicje wszystkich funkcjipImpl
składowych, do których istnieją odniesienia, do pliku .cpp. Dzięki temu możesz zachowaćAimpl
prywatność nagłówka i skrócić czas kompilacji.źródło
Aby umieścić przykład kształtu w kodzie:
Wynik to:
Zwróć uwagę na łatwość, z jaką nowe kolory i kształty można dodawać do systemu bez powodowania eksplozji podklas z powodu permutacji.
źródło
dla mnie myślę o tym jako o mechanizmie, w którym można wymieniać interfejsy. W prawdziwym świecie możesz mieć klasę, która może używać więcej niż jednego interfejsu, Bridge pozwala na zamianę.
źródło
Pracujesz dla firmy ubezpieczeniowej, w której tworzysz aplikację workflow, która zarządza różnego rodzaju zadaniami: księgowością, umową, roszczeniami. To jest abstrakcja. Po stronie wdrożenia musisz mieć możliwość tworzenia zadań z różnych źródeł: e-mail, faks, e-mailing.
Rozpoczynasz projektowanie od tych klas:
Teraz, ponieważ każde źródło musi być obsługiwane w określony sposób, decydujesz się na specjalizację każdego typu zadania:
Skończysz z 13 zajęciami. Dodanie typu zadania lub typu źródła staje się trudne. Użycie wzorca mostka daje coś łatwiejszego do utrzymania poprzez oddzielenie zadania (abstrakcji) od źródła (co jest problemem implementacyjnym):
Dodawanie typu zadania lub źródła jest teraz znacznie łatwiejsze.
Uwaga: większość programistów nie utworzyłaby z góry hierarchii 13 klas, aby rozwiązać ten problem. Jednak w prawdziwym życiu możesz nie znać z góry liczby źródeł i typów zadań; jeśli masz tylko jedno źródło i dwa typy zadań, prawdopodobnie nie oddzielisz zadania od źródła. Następnie ogólna złożoność rośnie w miarę dodawania nowych źródeł i typów zadań. W pewnym momencie dokonasz refaktoryzacji i najczęściej skończysz z rozwiązaniem podobnym do mostu.
źródło
źródło