2.2. Bridge

2.2.1. تعریف

دیزاین پترن Bridge یک الگوی طراحی ساختاری محسوب میشه که بر مبنای ایده ترجیح ترکیب به جای ارث بری بنا شده.

در واقع میشه گفت این دیزاین پترن به شما اجازه میده یک کلاس بزرگ یا مجموعه ای از کلاس های مرتبط با هم رو به دو سلسله مراتب مجزا یعنی انتزاع یا abstraction و پیاده سازی تقسیم کنید.

این الگو بیشتر زمانی مورد استفاده قرار میگیره که قراره برنامه ما از چند سیستم عامل یا چند زبان پشتیبانی کنه.

به نظرتون پیچیده میاد؟

نگران نباشید، ادامه آموزش رو که بخونید کاملا متوجه مفهومش میشید.

2.2.2. اجزاء

الگوی طراحی Bridge از چند بخش اصلی تشکیل میشه:

  1. Abstraction: یک interface سطح بالا محسوب میشه که client با ارتباط با اون میتونه با سیستم مد نظر در ارتباط باشه.

2. Implementation: شامل interface سطح پایین که تعریف می کنه عملیات abstraction چطور باید اتفاق بیفته، همچنین باید گونه ای پیاده سازی بشه که مستقل از جزئیات abstraction باشه.

UML of Bridge Design Pattern

Radowod, CC BY-SA 3.0, via Wikimedia Commons

2.2.3. چه زمانی استفاده میشه؟

این دیزاین پترن رو زمانی استفاده می کنیم که قصد تقسیم و سازمان دهی یک کلاس یکپارچه شامل چند گونه از چند عملکرد رو داشته باشیم.

مثلا زمانی که یک کلاس امکان کار با چند دیتابیس یا سیستم عامل مختلف رو داشته باشه و نخوایم مثلا به ازای 3 سیستم عامل مختلف برای 4 کلاس مختلف، 3 ضربدر 4، یعنی 12 کلاس با نام های مختلف مختلف بسازیم!

و همچنین زمانی مورد استفاده قرار میگیره که بخوایم یک کلاس موجود رو در چند سطح مختلف (و مستقل) گسترش بدیم.

Caution

✅ مزایای استفاده

امکان ایجاد برنامه ها و کلاس های مستقل از پلتفرم اجرایی، یا چند بستری

رعایت اصول Open/Closed و تک مسئولیتی از اصول Solid با ایجاد امکان گسترش abstraction ها و implementation ها به صورت مستقل از همدیگر

Warning

❌ معایب استفاده

به علت افزایش تعداد کلاس ها و… پیچیدگی برنامه قطعا افزایش پیدا می کنه

2.2.4. کاربرد عملی

خب فرض کنید یک صفحه وب داریم که دو تم Light و Dark داره. (یا حتی بیشتر)

برای پیاده سازی اون میتونیم از دیزاین پترن Bridge استفاده کنیم.

2.2.5. پیاده سازی

خب قبل از هر چیز مربوط به تم رو داریم:

1<?php
2
3interface Theme
4{
5    public function getBackgroundColor(): string;
6
7    public function getTextColor(): string;
8}

و بعد هم پیاده سازی های مربوط به تم تیره و روشن:

 1<?php
 2
 3class LightTheme implements Theme
 4{
 5    public function getBackgroundColor(): string
 6    {
 7        return "#FFFFFF";
 8    }
 9
10    public function getTextColor(): string
11    {
12        return "#000000";
13    }
14}
15
16class DarkTheme implements Theme
17{
18    public function getBackgroundColor(): string
19    {
20        return "#1E1E1E";
21    }
22
23    public function getTextColor(): string
24    {
25        return "#FFFFFF";
26    }
27}

خب حالا میریم سراغ interface به نام WebPage که به این صورت تعریف میشه:

1<?php
2
3interface WebPage
4{
5    public function getContent(): string;
6}

و کلاس AbstractWebPage که WebPage رو پیاده سازی می کنه:

 1<?php
 2
 3abstract class AbstractWebPage implements WebPage
 4{
 5    protected Theme $theme;
 6
 7    public function __construct(Theme $theme)
 8    {
 9        $this->theme = $theme;
10    }
11
12    public function setTheme(Theme $theme)
13    {
14        $this->theme = $theme;
15    }
16
17    public function getBackgroundColor(): string
18    {
19        return $this->theme->getBackgroundColor();
20    }
21
22    public function getTextColor(): string
23    {
24        return $this->theme->getTextColor();
25    }
26
27    abstract public function getContent(): string;
28}

و در نهایت میتونیم برای صفحات مختلف به این شکل عمل کنیم:

 1<?php
 2
 3class HomePage extends AbstractWebPage
 4{
 5    public function getContent(): string
 6    {
 7        return "<div style='background-color: {$this->getBackgroundColor()}; color: {$this->getTextColor()};'>Welcome to our website!</div>";
 8    }
 9}
10
11class AboutPage extends AbstractWebPage
12{
13    public function getContent(): string
14    {
15        return "<div style='background-color: {$this->getBackgroundColor()}; color: {$this->getTextColor()};'>Learn more about us...</div>";
16    }
17}

2.2.6. نحوه فراخوانی

 1<?php
 2
 3// Usage example
 4$lightTheme = new LightTheme();
 5$darkTheme = new DarkTheme();
 6
 7$homePage = new HomePage($lightTheme);
 8echo $homePage->getContent() . "<br>";
 9
10$homePage->setTheme($darkTheme);
11echo $homePage->getContent() . "<br>";
12
13$aboutPage = new AboutPage($darkTheme);
14echo $aboutPage->getContent() . "<br>";

میبینید که اینجا دیگه لازم نیست ما به ازای هر نوع تم یک کلاس مجزا مثل DarkThemeHomePage و LightThemeHomePage داشته باشیم و با استفاده از الگوی طراحی Bridge تونستیم این مسئله رو به این شکل حل کنیم.