Mi a híd mintája?
A hídminta egy szerkezeti tervezési minta. Más szóval, fő feladata egy teljes értékű struktúra létrehozása osztályokból és objektumokból. A híd ezt úgy teszi meg, hogy egy vagy több osztályt külön hierarchiára oszt fel: absztrakcióra és megvalósításra . A funkcionalitás változása az egyik hierarchiában nem von maga után változást a másikban. Ez mind szép és jó, de ez a meghatározás nagyon tág, és nem ad választ a legfontosabb kérdésre: "Mi az a hídminta?" Azt hiszem, könnyebben megértheti a gyakorlati alkalmazását. Tehát rögtön hozzunk létre egy klasszikus forgatókönyvet a hídmintához. Van egy absztraktShape
osztályunk, amely egy általános geometriai alakzatot képvisel:
-
Shape.java
public abstract class Shape { public abstract void draw(); }
Amikor úgy döntünk, hogy alakzatokat, például háromszögeket és téglalapokat adunk hozzá, örökölni fogják az
Shape
osztályt: -
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()
ettől a színtől függ. Ahhoz, hogy a metódus különböző megvalósításai legyenek draw()
, minden alakzat-szín kombinációhoz létre kell hoznunk egy osztályt. Ha három színünk van, akkor hat osztályra van szükségünk: TriangleBlack
, TriangleGreen
, TriangleRed
, RectangleBlack
, RectangleGreen
és RectangleRed
. A hat osztály nem olyan nagy probléma. De! Ha új formát vagy színt kell hozzáadnunk, akkor az osztályok száma exponenciálisan nő. Hogyan lehet kikerülni ebből a helyzetből? Nem a legjobb megoldás a színek tárolása egy mezőben és az összes lehetőség felsorolása feltételes utasításokkal. Jó megoldás a színek áthelyezése egy külön felületre. Alig van szó: hozzunk létre egy Color
felületet három megvalósítással: BlackColor
, GreenColor
és 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"); } }
Most hozzáadunk egy
Color
mezőt az osztályhozShape
. Értékét a konstruktorban fogjuk megtalálni. -
Shape.java:
public abstract class Shape { protected Color color; public Shape(Color color) { this.color = color; } public abstract void draw(); }
color
A változót az implementációkban fogjuk használniShape
. Ez azt jelenti, hogy az alakzatok mostantól használhatják aColor
felület funkcióit. -
Téglalap.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
mező egy híd, amely két különálló osztályhierarchiát köt össze.
Hogyan építsünk hidat: absztrakció és megvalósítás
Nézzünk meg egy osztálydiagramot, amely a hídmintát ábrázolja:
- Az absztrakció az
Shape
osztály - A RefinedAbstraction az
Triangle
ésRectangle
osztályok - A végrehajtó az
Color
interfész - A ConcreteImplementor a
BlackColor
,GreenColor
ésRedColor
osztályok.
Shape
osztály egy absztrakció – az alakzatok különféle színekkel való kitöltésének kezelésére szolgáló mechanizmus, amely az interfészre Color
(Implementor) delegálódik. A Triangle
és Rectangle
osztályok konkrét osztályok, amelyek az osztály által elérhetővé tett mechanizmust használják Shape
. BlackColor
, GreenColor
és RedColor
konkrét megvalósítások a megvalósítási hierarchiában.
Hol kell használni a hídmintát
Ennek a mintának az a hatalmas előnye, hogy az egyik hierarchiában a funkcionális osztályokat módosíthatja anélkül, hogy megtörné a másik logikáját. Ezenkívül ez a megközelítés segít csökkenteni az osztályok közötti kapcsolódást. Ennek a mintának a fő követelménye az, hogy „kövesse az utasításokat” – ne hagyja figyelmen kívül egyiket sem! Ebből a célból találjuk ki azokat a helyzeteket, amikor feltétlenül használnia kell a hídmintát:-
Ha két fogalom (pl. formák és színek) kombinációi alapján kell bővítenie az entitások számát.
-
Ha egy nagy osztályt, amely nem felel meg az egyfelelősség elvének, kisebb osztályokra szeretne felosztani, amelyek szűk funkcionalitással rendelkeznek.
-
Ha a program futása közben bizonyos entitások logikáján módosítani kell.
-
Ha el kell rejteni egy implementációt az osztály vagy a könyvtár kliensei elől.
A minta előnyei és hátrányai
A többi mintához hasonlóan a hídnak is vannak előnyei és hátrányai. A hídminta előnyei:- Javítja a kód méretezhetőségét – funkcionalitást bővíthet anélkül, hogy félne attól, hogy a program egy másik részében valami elromlik.
- Csökkenti az alosztályok számát, ha az entitások száma egyébként két fogalom (például formák és színek) kombinációján alapulna.
- Lehetővé teszi, hogy két különálló hierarchián – absztrakción és megvalósításon – külön dolgozzon. Két különböző fejlesztő módosíthat anélkül, hogy belemerülne egymás kódjának részleteibe.
- Csökkenti az osztályok közötti csatolást – az egyetlen hely, ahol a két osztály összekapcsolódik, a híd (azaz a
Color color
mező).
- A konkrét helyzettől és a projekt általános szerkezetétől függően ez negatívan befolyásolhatja a program teljesítményét (például ha több objektumot kell inicializálnia).
- Ez kevésbé olvashatóvá teszi a kódot, mivel váltani kell a két osztály között.
GO TO FULL VERSION