A híd programtervezési minta egy szoftverfejlesztésben használt tervezési minta, mely azt jelenti, hogy "különválasztjuk az absztrakciót az implementációjától, hogy a kettőt függetlenül lehessen variálni."[1] A híd egységbe zárást, aggregációt, és öröklődést használ, hogy a felelősségi köröket különböző osztályokba különítse el.
A híd mintára kétrétegű absztrakcióként is tekinthetünk. Ez általában azt jelenti, hogy adva van két interfész (a híd két "pillére"), az egyik magaszintű művelet(ek)et, a másik alacsonyszintű művelet(ek)et deklarál; és a magasszintű interfész implementációi az alacsonyszintű interfész tetszőleges implementációjával együttműködnek (és azt a konstruktorban veszik át). Ez lehetővé teszi, hogy a rétegek egymástól függetlenül cserélhetők legyenek.
Előfordul, hogy csak egy fix implementáció létezik, ez a minta Pimpl idiómaként is ismert a C++ világban.
A híd minta nem azonos az illesztő (adapter) mintával, bár a híd mintát gyakran valósítják meg az osztály illesztő minta felhasználásával (ld. a lenti példákat).
A híd minta a függőség befecskendezésének (dependency injection) egyik lehetséges módja.
A következő Java program alakzatok kirajzolásának példáján keresztül illusztrálja a híd mintát.
/** "Implementor" */ interface DrawingAPI { public void drawCircle(double x, double y, double radius); } /** "ConcreteImplementor" 1/2 */ class DrawingAPI1 implements DrawingAPI { public void drawCircle(double x, double y, double radius) { System.out.printf("API1.circle at %f:%f radius %f\n", x, y, radius); } } /** "ConcreteImplementor" 2/2 */ class DrawingAPI2 implements DrawingAPI { public void drawCircle(double x, double y, double radius) { System.out.printf("API2.circle at %f:%f radius %f\n", x, y, radius); } } /** "Abstraction" */ abstract class Shape { protected DrawingAPI drawingAPI; protected Shape(DrawingAPI drawingAPI){ this.drawingAPI = drawingAPI; } public abstract void draw(); // low-level public abstract void resizeByPercentage(double pct); // high-level } /** "Refined Abstraction" */ class CircleShape extends Shape { private double x, y, radius; public CircleShape(double x, double y, double radius, DrawingAPI drawingAPI) { super(drawingAPI); this.x = x; this.y = y; this.radius = radius; } // low-level i.e. Implementation specific public void draw() { drawingAPI.drawCircle(x, y, radius); } // high-level i.e. Abstraction specific public void resizeByPercentage(double pct) { radius *= pct; } } /** "Client" */ class BridgePatternExample { public static void main(String[] args) { Shape[] shapes = new Shape[] { new CircleShape(1, 2, 3, new DrawingAPI1()), new CircleShape(5, 7, 11, new DrawingAPI2()), }; for (Shape shape : shapes) { shape.resizeByPercentage(2.5); shape.draw(); } } }
Kimenete:
API1.circle at 1.000000:2.000000 radius 7.5000000 API2.circle at 5.000000:7.000000 radius 27.500000
PHP nyelvű példa.
interface DrawingAPI { function drawCircle($dX, $dY, $dRadius); } class DrawingAPI1 implements DrawingAPI { public function drawCircle($dX, $dY, $dRadius) { echo "API1.circle at $dX:$dY radius $dRadius.<br/>"; } } class DrawingAPI2 implements DrawingAPI { public function drawCircle($dX, $dY, $dRadius) { echo "API2.circle at $dX:$dY radius $dRadius.<br/>"; } } abstract class Shape { protected $oDrawingAPI; public abstract function draw(); public abstract function resizeByPercentage($dPct); protected function __construct(DrawingAPI $oDrawingAPI) { $this->oDrawingAPI = $oDrawingAPI; } } class CircleShape extends Shape { private $dX; private $dY; private $dRadius; public function __construct($dX, $dY, $dRadius, DrawingAPI $oDrawingAPI) { parent::__construct($oDrawingAPI); $this->dX = $dX; $this->dY = $dY; $this->dRadius = $dRadius; } public function draw() { $this->oDrawingAPI->drawCircle( $this->dX, $this->dY, $this->dRadius ); } public function resizeByPercentage($dPct) { $this->dRadius *= $dPct; } } class Tester { public static function main() { $aShapes = array( new CircleShape(1, 3, 7, new DrawingAPI1()), new CircleShape(5, 7, 11, new DrawingAPI2()), ); foreach ($aShapes as $shape) { $shape->resizeByPercentage(2.5); $shape->draw(); } } } Tester::main();
API1.circle at 1:3 radius 17.5 API2.circle at 5:7 radius 27.5
Scala nyelvű példa.
trait DrawingAPI { def drawCircle(x: Double, y: Double, radius: Double) } class DrawingAPI1 extends DrawingAPI { def drawCircle(x: Double, y: Double, radius: Double) = println(s"API #1 $x $y $radius") } class DrawingAPI2 extends DrawingAPI { def drawCircle(x: Double, y: Double, radius: Double) = println(s"API #2 $x $y $radius") } abstract class Shape(drawingAPI: DrawingAPI) { def draw() def resizePercentage(pct: Double) } class CircleShape(x: Double, y: Double, var radius: Double, drawingAPI: DrawingAPI) extends Shape(drawingAPI: DrawingAPI) { def draw() = drawingAPI.drawCircle(x, y, radius) def resizePercentage(pct: Double) { radius *= pct } } object BridgePatternExample { def main(args: Array[String]) { Seq ( new CircleShape(1, 3, 5, new DrawingAPI1), new CircleShape(4, 5, 6, new DrawingAPI2) ) foreach { x => x.resizePercentage(3) x.draw() } } }
Ez a szócikk részben vagy egészben a Bridge pattern című angol Wikipédia-szócikk ezen változatának fordításán alapul. Az eredeti cikk szerkesztőit annak laptörténete sorolja fel. Ez a jelzés csupán a megfogalmazás eredetét és a szerzői jogokat jelzi, nem szolgál a cikkben szereplő információk forrásmegjelöléseként.