الگوی پل، یک الگوی طراحی در مهندسی نرم‌افزار است که به معنای *"جداسازی یک انتزاع از اجرای آن به طوری که این دو بتوانند به صورت مستقل تغییر پذیر باشند."*می‌باشد. این الگو توسط **باند چهار نفره (GoF)** معرفی شده است. *الگوی* *پل* از گروه‌های قالب‌دار و گروه‌های تجمعی و بعضاً ارث‌بری برای جداسازی مسئولیتها در طبقات مختلف استفاده می‌کند.

هنگامی که یک کلاس اغلب تغییر می‌کند، ویژگی‌های **برنامه‌نویسی شی گرا** بسیار مفید خواهد بود، چرا که تغییرات در کد برنامه، می‌تواند با حداقل اطلاعات از برنامه صورت گیرد. زمانی که کلاس‌ها و کاری که آن‌ها انجام می‌دهند نسبت به یگدیگر تفاوت‌های زیادی داشته باشد، از الگوی پل استفاده می‌شود. خود کلاس به عنوان انتزاع در نظر گرفته می‌شود و کاری که انجام می‌دهد در مرحله پیاده‌سازی آن است. همچنین الگوی پل می‌تواند به عنوان دو لایه از انتزاع در نظر گرفته شود.

زمانی که تنها یک پیاده‌سازی ثابت امکان‌پذیر است در زبان C++ این الگو در اصطلاح **Pimpl** شناخته می‌شود.

**الگوی پل** اغلب با **الگوی آداپتور** اشتباه گرفته می‌شود. در واقع، **الگوی پل** اغلب در زبان جاوا توسط کلاس **الگوی آداپتور**پیاده‌سازی می‌شود. مانند مثالی که در ادامه آمده است.

**انواع دیگر**: جداسازی بیشتر پیاده‌سازی با تعویق آن در حدی که از انتزاع استفاده شود، قابل انجام است.

ساختار
------

Abstraction (کلاس انتزاعی)
رابط انتزاعی را تعریف می‌کند.
مجری پیاده‌سازی را تأمین می‌کند.
RefinedAbstraction (کلاس عادی)
رابط تعریف شده در انتزاع را ارائه می‌دهد.
Implementor (رابط کاربری)
رابط کلاس‌های پیاده‌سازی شده را تعریف می‌کند.
ConcreteImplementor (کلاس عادی)
رابط مجری پیاده‌سازی را پیاده‌سازی می‌کند.
پل در LePUS3 (افسانه)

مثال
----

### C

الگوی پل در ساختار درخت شیءها را قرار می‌دهد. این الگو انتراع را از پیاده‌سازی جدا می‌کند. در این جا انتزاع نقش مشتری ای را اجرا می‌کند که اشیاء از آن فراخوانی می‌شوند. مثالی برای پیاده‌سازی در C# در ادامه آمده است:

```
// Helps in providing truly decoupled architecture
public interface IBridge
{
 void Function1();
 void Function2();
}

public class Bridge1 : IBridge
{
 public void Function1()
 {
 Console.WriteLine("Bridge1.Function1");
 }

 public void Function2()
 {
 Console.WriteLine("Bridge1.Function2");
 }
}

public class Bridge2 : IBridge
{
 public void Function1()
 {
 Console.WriteLine("Bridge2.Function1");
 }

 public void Function2()
 {
 Console.WriteLine("Bridge2.Function2");
 }
}

public interface IAbstractBridge
{
 void CallMethod1();
 void CallMethod2();
}

public class AbstractBridge : IAbstractBridge
{
 public IBridge bridge;

 public AbstractBridge(IBridge bridge)
 {
 this.bridge = bridge;
 }

 public void CallMethod1()
 {
 this.bridge.Function1();
 }

 public void CallMethod2()
 {
 this.bridge.Function2();
 }
}

```
همان طوری که می‌بینید، کلاس‌های پل، همگی از معماری رابط-محور متشابهی برای ساخت اشیاء استفاده می‌کنند. از طرف دیگر، انتزاع، یک شیء از مرحله پیاده‌سازی را گرفته و آن را اجرا می‌کند. در نتیجه، آن‌ها را کاملاً از یکدیگر جدا می‌کند.

### Crystal

```
abstract class DrawingAPI
 abstract def draw\_circle(x : Float64, y : Float64, radius : Float64)
end

class DrawingAPI1 < DrawingAPI
 def draw\_circle(x : Float, y : Float, radius : Float)
 "API1.circle at #{x}:#{y} - radius: #{radius}"
 end
end

class DrawingAPI2 < DrawingAPI
 def draw\_circle(x : Float64, y : Float64, radius : Float64)
 "API2.circle at #{x}:#{y} - radius: #{radius}"
 end
end

abstract class Shape
 protected getter drawing\_api : DrawingAPI

 def initialize(@drawing\_api)
 end

 abstract def draw
 abstract def resize\_by\_percentage(percent : Float64)
end

class CircleShape < Shape
 getter x : Float64
 getter y : Float64
 getter radius : Float64

 def initialize(@x, @y, @radius, drawing\_api : DrawingAPI)
 super(drawing\_api)
 end

 def draw
 @drawing\_api.draw\_circle(@x, @y, @radius)
 end

 def resize\_by\_percentage(percent : Float64)
 @radius \*= (1 + percent/100)
 end
end

class BridgePattern
 def self.test
 shapes = [] of Shape
 shapes << CircleShape.new(1.0, 2.0, 3.0, DrawingAPI1.new)
 shapes << CircleShape.new(5.0, 7.0, 11.0, DrawingAPI2.new)

 shapes.each do |shape|
 shape.resize\_by\_percentage(2.5)
 puts shape.draw
 end
 end
end

BridgePattern.test

```
خروجی

```
API1.circle at 1.0:2.0 - radius: 3.075
API2.circle at 5.0:7.0 - radius: 11.275

```

### جاوا

این برنامه جاوا (SE 6) یک شکل (shape) را نشان می‌دهد.

```
/\*\* "Implementor" \*/
interface DrawingAPI {
 public void drawCircle(final double x, final double y, final double radius);
}

/\*\* "ConcreteImplementor" 1/2 \*/
class DrawingAPI1 implements DrawingAPI {
 public void drawCircle(final double x, final double y, final 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(final double x, final double y, final 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(final DrawingAPI drawingAPI){
 this.drawingAPI = drawingAPI;
 }

 public abstract void draw(); // low-level
 public abstract void resizeByPercentage(final double pct); // high-level
}

/\*\* "Refined Abstraction" \*/
class CircleShape extends Shape {
 private double x, y, radius;
 public CircleShape(final double x, final double y, final double radius, final 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(final double pct) {
 radius \*= (1.0 + pct/100.0);
 }
}

/\*\* "Client" \*/
class BridgePattern {
 public static void main(final 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();
 }
 }
}

```
خروجی آن:

```
API1.circle at 1.000000:2.000000 radius 3.075000
API2.circle at 5.000000:7.000000 radius 11.275000

```

### PHP

```
interface DrawingAPI {
    function drawCircle($x, $y, $radius);
}

class DrawingAPI1 implements DrawingAPI {
    public function drawCircle($x, $y, $radius) {
        echo "API1.circle at $x:$y radius $radius.\n";
    }
}

class DrawingAPI2 implements DrawingAPI {
    public function drawCircle($x, $y, $radius) {
        echo "API2.circle at $x:$y radius $radius.\n";
    }
}

abstract class Shape {
    protected $drawingAPI;

    public abstract function draw();
    public abstract function resizeByPercentage($pct);

    protected function \_\_construct(DrawingAPI $drawingAPI) {
        $this->drawingAPI = $drawingAPI;
    }
}

class CircleShape extends Shape {
    private $x;
    private $y;
    private $radius;

    public function \_\_construct($x, $y, $radius, DrawingAPI $drawingAPI) {
        parent::\_\_construct($drawingAPI);
        $this->x = $x;
        $this->y = $y;
        $this->radius = $radius;
    }

    public function draw() {
        $this->drawingAPI->drawCircle($this->x, $this->y, $this->radius);
    }

    public function resizeByPercentage($pct) {
        $this->radius \*= $pct;
    }
}

class Tester {
    public static function main()  {
        $shapes = array(
            new CircleShape(1, 3, 7,  new DrawingAPI1()),
            new CircleShape(5, 7, 11, new DrawingAPI2()),
        );

        foreach ($shapes 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

```
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 BridgePattern {
 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()
 }
 }
}

```

جستارهای وابسته
---------------

* الگوهای طراحی
* آداپتور الگوی
* الگوی استراتژی

منابع
-----

1. ↑  Gamma, E, Helm, R, Johnson, R, Vlissides, J: *Design Patterns*, page 151.

پیوند به بیرون
--------------

* Bridge in UML and in LePUS3 (یک زبان مدل سازی فرمال)
* "C# Design Patterns: The Bridge Pattern". *Sample Chapter*. از: James W. Cooper. *C# Design Patterns: A Tutorial*. Addison-Wesley. ISBN 0-201-84453-2.

| * ن
* ب
* و
الگوهای طراحی |
| --- |
| الگوهای طراحی GO4 | 

|  |  |
| --- | --- |
| ایجاد | 
* الگوی کارخانه انتزاعی
* الگوی سازنده
* الگوی متد کارخانه شیء
* الگوی نمونه اولیه
* الگوی یگانه

 |
| ساختاری | 
* آداپتور
* پل
* کامپوزیت
* آذینگر
* نما
* مگس وزن
* وکالت

 |
| رفتاری | 
* زنجیره مسئولیت
* الگوی فرمان
* مفسر
* الگوی تکرار
* میانجی
* یادگاری
* ناظر
* وضعیت
* استراتژی
* متد الگو
* بازدیدگر

 |

 |
| Concurrencypatterns | 
* Active object
* Balking
* Binding properties
* Double-checked locking
* Event-based asynchronous
* Guarded suspension
* Join
* قفل
* مانیتور
* Proactor
* Reactor
* Read write lock
* زمان‌بندی
* الگوی مخزن نخ
* Thread-local storage

 |
| الگوهایمعماری | 
* Front controller
* مفسر
* مدل-نما-کنترل‌گر
* ADR
* Entity-component-system
* چندلایه
* Specification
* Publish–subscribe
* اشیای لخت
* Service locator
* ثبت کنشور
* Identity map
* شی دسترسی به داده
* شی انتقال داده
* وارونگی کنترل
* Model 2

 |
| دیگرالگوها | 
* Blackboard
* Business delegate
* Composite entity
* تزریق نیازمندی
* Intercepting filter
* بارگیری تنبلانه
* شیء ساختگی
* Null object
* استخر اشیاء
* Servant
* Twin
* Type tunnel
* Method chaining

 |
| کتاب‌ها | 
* *الگوهای طراحی*
* *Enterprise Integration Patterns*
* *Patterns of Enterprise Application Architecture*
* *Analysis patterns*

 |
| افراد | 
* کریستوفر الکساندر
* Erich Gamma
* Ralph Johnson
* John Vlissides
* گریدی بوچ
* کنت بک
* وارد کانینگهام
* مارتین فولر
* رابرت سسیل مارتین
* Jim Coplien
* Douglas Schmidt
* Linda Rising

 |
| جوامع | 
* The Hillside Group
* The Portland Pattern Repository

 |