---
title: "الجسر"
type: "design-pattern"
slug: "bridge"
url: "http://localhost:3000/ar/design-patterns/bridge.md"
category: "الأنماط الهيكلية"
description: "الجسر هو نمط تصميم هيكلي يتيح لك تقسيم كلاس ضخم أو مجموعة من الكلاسات المترابطة إلى تسلسلين هرميين منفصلين — التجريد والتنفيذ — يمكن تطويرهما بشكل مستقل عن بعضهما."
languages: ["java", "csharp", "cpp", "go", "php", "python", "ruby", "rust", "swift", "typescript"]
---
# الجسر

> الجسر هو نمط تصميم هيكلي يتيح لك تقسيم كلاس ضخم أو مجموعة من الكلاسات المترابطة إلى تسلسلين هرميين منفصلين — التجريد والتنفيذ — يمكن تطويرهما بشكل مستقل عن بعضهما.

## Intent

**الجسر** هو نمط تصميم هيكلي يتيح لك تقسيم كلاس ضخم أو مجموعة من الكلاسات المترابطة إلى تسلسلين هرميين منفصلين — التجريد والتنفيذ — يمكن تطويرهما بشكل مستقل عن بعضهما.

## Problem

_التجريد؟_ _التنفيذ؟_ يبدو الأمر مخيفاً؟ لا تقلق، دعنا نتأمل مثالاً بسيطاً.

لنفترض أن لديك كلاساً هندسياً `Shape` مع زوج من الكلاسات الفرعية: `Circle` و`Square`. تريد توسيع هذا التسلسل الهرمي ليشمل الألوان، لذا تخطط لإنشاء كلاسات فرعية `Red` و`Blue`. غير أنك بما أن لديك كلاسين فرعيين بالفعل، ستحتاج إلى إنشاء أربع تركيبات مثل `BlueCircle` و`RedSquare`.

عدد تركيبات الكلاسات يتزايد بتقدم هندسي.

إضافة أنواع جديدة من الأشكال والألوان إلى التسلسل الهرمي ستُنمِّيه بشكل أسي. على سبيل المثال، لإضافة شكل مثلث ستحتاج إلى إدخال كلاسين فرعيين، أحدهما لكل لون. وبعد ذلك، إضافة لون جديد ستستلزم إنشاء ثلاثة كلاسات فرعية، واحد لكل نوع من الأشكال. كلما تقدمنا، كلما ساءت الأمور.

## Solution

تنشأ هذه المشكلة لأننا نحاول توسيع كلاسات الأشكال في بُعدين مستقلين: حسب الشكل وحسب اللون. وهذه مشكلة شائعة جداً في الوراثة الكلاسية.

يحاول نمط الجسر حل هذه المشكلة بالتحول من الوراثة إلى تركيب الكائنات. يعني ذلك استخراج أحد الأبعاد في تسلسل هرمي منفصل، بحيث تُشير الكلاسات الأصلية إلى كائن من التسلسل الهرمي الجديد، بدلاً من احتواء كل الحالة والسلوكيات في كلاس واحد.

يمكنك منع الانفجار في التسلسل الهرمي للكلاسات بتحويله إلى عدة تسلسلات هرمية مترابطة.

باتباع هذا النهج، يمكننا استخراج الكود المتعلق بالألوان في كلاسه الخاص مع كلاسين فرعيين: `Red` و`Blue`. يحصل كلاس `Shape` بعد ذلك على حقل مرجع يشير إلى أحد كائنات الألوان. يمكن للشكل الآن تفويض أي عمل متعلق بالألوان إلى كائن اللون المرتبط به. سيعمل ذلك المرجع كجسر بين كلاسَي `Shape` و`Color`. من الآن فصاعداً، إضافة ألوان جديدة لن تستلزم تغيير التسلسل الهرمي للأشكال، والعكس صحيح.

#### التجريد والتنفيذ

يُقدِّم كتاب GoF "عصابة الأربعة" هو لقب يُطلق على المؤلفين الأربعة للكتاب الأصلي عن أنماط التصميم: _Design Patterns: Elements of Reusable Object-Oriented Software_ <https://refactoring.guru/gof-book>. مصطلحَي _التجريد_ و_التنفيذ_ كجزء من تعريف نمط الجسر. في رأيي، يبدو هذان المصطلحان أكاديميَّين للغاية ويجعلان النمط يبدو أكثر تعقيداً مما هو عليه فعلاً. بعد قراءة المثال البسيط عن الأشكال والألوان، دعنا نفك شفرة الكلمات المخيفة في كتاب GoF.

_التجريد_ (يُسمى أيضاً _الواجهة_) هو طبقة تحكم عالية المستوى لكيان ما. لا يُفترض أن تُنجز هذه الطبقة أي عمل حقيقي بنفسها، بل يجب أن تُفوِّض العمل إلى طبقة _التنفيذ_ (يُسمى أيضاً _المنصة_).

لاحظ أننا لا نتحدث عن _الواجهات_ أو _الكلاسات التجريدية_ من لغة البرمجة الخاصة بك. هذه ليست الشيء نفسه.

عند الحديث عن التطبيقات الحقيقية، يمكن تمثيل التجريد بواجهة المستخدم الرسومية (GUI)، وقد يكون التنفيذ هو كود نظام التشغيل الأساسي (API) الذي تستدعيه طبقة واجهة المستخدم الرسومية استجابةً لتفاعلات المستخدم.

بشكل عام، يمكنك توسيع مثل هذا التطبيق في اتجاهين مستقلين:

* امتلاك عدة واجهات مستخدم رسومية مختلفة (على سبيل المثال، مُصمَّمة للعملاء العاديين أو المسؤولين).
* دعم عدة واجهات برمجة تطبيقات مختلفة (على سبيل المثال، للتمكن من تشغيل التطبيق على Windows وLinux وmacOS).

في أسوأ سيناريو ممكن، قد يبدو هذا التطبيق وعاءً هائلاً من السباغيتي، حيث تربط مئات الشروط أنواعاً مختلفة من واجهات المستخدم الرسومية بمختلف واجهات برمجة التطبيقات في أرجاء الكود.

إجراء حتى تغيير بسيط على قاعدة كود ضخمة أمر صعب للغاية لأنك يجب أن تفهم _كل شيء_ جيداً. إجراء التغييرات على وحدات أصغر ومُعرَّفة بدقة أسهل بكثير.

يمكنك إحلال النظام في هذه الفوضى باستخراج الكود المتعلق بتركيبات واجهة-منصة محددة في كلاسات منفصلة. غير أنك ستكتشف قريباً أن هناك _الكثير_ من هذه الكلاسات. سينمو التسلسل الهرمي للكلاسات بشكل أسي لأن إضافة واجهة مستخدم رسومية جديدة أو دعم واجهة برمجة تطبيقات مختلفة سيستلزم إنشاء المزيد والمزيد من الكلاسات.

دعنا نحاول حل هذه المشكلة باستخدام نمط الجسر. يقترح تقسيم الكلاسات إلى تسلسلين هرميين:

* التجريد: طبقة واجهة المستخدم الرسومية للتطبيق.
* التنفيذ: واجهات برمجة التطبيقات الخاصة بأنظمة التشغيل.

أحد الطرق لهيكلة تطبيق متعدد المنصات.

يتحكم كائن التجريد في مظهر التطبيق، مُفوِّضاً العمل الفعلي إلى كائن التنفيذ المرتبط به. التنفيذات المختلفة قابلة للتبادل طالما أنها تتبع واجهة مشتركة، مما يتيح لنفس واجهة المستخدم الرسومية العمل على Windows وLinux.

نتيجةً لذلك، يمكنك تغيير كلاسات واجهة المستخدم الرسومية دون المساس بالكلاسات المتعلقة بواجهة برمجة التطبيقات. علاوة على ذلك، إضافة دعم لنظام تشغيل آخر تستلزم فقط إنشاء كلاس فرعي في تسلسل التنفيذ الهرمي.

## Structure

1. يوفر **التجريد** منطق التحكم عالي المستوى. ويعتمد على كائن التنفيذ لأداء العمل الفعلي على المستوى المنخفض.
2. يُعلن **التنفيذ** عن الواجهة المشتركة لجميع التنفيذات الملموسة. يمكن للتجريد التواصل مع كائن التنفيذ فقط عبر الأساليب المُعلَن عنها هنا.
قد يُدرج التجريد نفس أساليب التنفيذ، لكنه عادةً يُعلن عن سلوكيات معقدة تعتمد على مجموعة واسعة من العمليات الأساسية المُعلَن عنها في التنفيذ.
3. تحتوي **التنفيذات الملموسة** على كود خاص بالمنصة.
4. توفر **التجريدات المُحسَّنة** متغيرات من منطق التحكم. وكوالديها، تعمل مع تنفيذات مختلفة عبر واجهة التنفيذ العامة.
5. عادةً يهتم **العميل** فقط بالعمل مع التجريد. غير أن مهمة العميل هي ربط كائن التجريد بأحد كائنات التنفيذ.

## Pseudocode

يوضح هذا المثال كيف يمكن لنمط **الجسر** تقسيم الكود الضخم لتطبيق يدير الأجهزة وأجهزة التحكم عن بُعد الخاصة بها. تعمل كلاسات `Device` كتنفيذ، في حين تعمل كلاسات `Remote` كتجريد.

يُقسَّم التسلسل الهرمي الأصلي للكلاسات إلى جزأين: الأجهزة وأجهزة التحكم عن بُعد.

يُعلن كلاس جهاز التحكم الأساسي عن حقل مرجع يربطه بكائن الجهاز. تعمل جميع أجهزة التحكم مع الأجهزة عبر واجهة الجهاز العامة، مما يتيح لجهاز التحكم ذاته دعم أنواع متعددة من الأجهزة.

يمكنك تطوير كلاسات أجهزة التحكم بشكل مستقل عن كلاسات الأجهزة. كل ما تحتاجه هو إنشاء كلاس فرعي جديد لجهاز التحكم. على سبيل المثال، قد يحتوي جهاز التحكم الأساسي على زرين فقط، لكن يمكنك توسيعه بميزات إضافية، كبطارية إضافية أو شاشة تعمل باللمس.

يربط كود العميل النوع المطلوب من جهاز التحكم بكائن جهاز محدد عبر مُنشئ جهاز التحكم.

// يُعرِّف "التجريد" الواجهةَ للجزء "التحكمي"
// من التسلسلين الهرميين للكلاسات. ويحتفظ بمرجع
// لكائن من تسلسل "التنفيذ" الهرمي ويُفوِّض
// كل العمل الفعلي لهذا الكائن.
class RemoteControl is
    protected field device: Device
    constructor RemoteControl(device: Device) is
        this.device = device
    method togglePower() is
        if (device.isEnabled()) then
            device.disable()
        else
            device.enable()
    method volumeDown() is
        device.setVolume(device.getVolume() - 10)
    method volumeUp() is
        device.setVolume(device.getVolume() + 10)
    method channelDown() is
        device.setChannel(device.getChannel() - 1)
    method channelUp() is
        device.setChannel(device.getChannel() + 1)

// يمكنك توسيع الكلاسات من تسلسل التجريد الهرمي
// بشكل مستقل عن كلاسات الأجهزة.
class AdvancedRemoteControl extends RemoteControl is
    method mute() is
        device.setVolume(0)

// تُعلن واجهة "التنفيذ" عن أساليب مشتركة لجميع
// كلاسات التنفيذ الملموسة. ولا يلزم أن تتطابق مع
// واجهة التجريد. في الواقع، قد تكون الواجهتان مختلفتين تماماً.
// عادةً توفر واجهة التنفيذ عمليات أساسية فقط، بينما
// يُعرِّف التجريد عمليات أعلى مستوى بناءً على تلك العمليات الأساسية.
interface Device is
    method isEnabled()
    method enable()
    method disable()
    method getVolume()
    method setVolume(percent)
    method getChannel()
    method setChannel(channel)

// جميع الأجهزة تتبع نفس الواجهة.
class Tv implements Device is
    // ...

class Radio implements Device is
    // ...

// في مكان ما في كود العميل.
tv = new Tv()
remote = new RemoteControl(tv)
remote.togglePower()

radio = new Radio()
remote = new AdvancedRemoteControl(radio)

## Applicability

استخدم نمط الجسر عندما تريد تقسيم وتنظيم كلاس ضخم يحتوي على عدة متغيرات من وظيفة معينة (على سبيل المثال، إذا كان الكلاس يمكنه العمل مع خوادم قواعد بيانات متعددة).

 كلما كبر الكلاس، كلما صعُب فهم آلية عمله وزاد الوقت اللازم لإجراء أي تغيير. إذ قد تستلزم التغييرات على أحد متغيرات الوظيفة إجراء تعديلات على الكلاس بأكمله، مما يؤدي في الغالب إلى وقوع أخطاء أو إغفال بعض الآثار الجانبية الحرجة.

يتيح لك نمط الجسر تقسيم الكلاس الضخم إلى عدة تسلسلات هرمية للكلاسات. وبعد ذلك يمكنك تعديل الكلاسات في كل تسلسل هرمي بشكل مستقل عن الكلاسات في التسلسلات الأخرى. يُبسِّط هذا النهج صيانة الكود ويُقلِّل من خطر كسر الكود الموجود.

 استخدم النمط عندما تحتاج إلى توسيع كلاس في عدة أبعاد متعامدة (مستقلة).

 يقترح الجسر استخراج تسلسل هرمي منفصل لكل بُعد من الأبعاد. يُفوِّض الكلاس الأصلي العمل المرتبط بتلك الأبعاد إلى الكائنات المنتمية إلى تلك التسلسلات الهرمية بدلاً من القيام بكل شيء بنفسه.

 استخدم الجسر إذا احتجت إلى تبديل التنفيذات في وقت التشغيل.

 على الرغم من كونه اختيارياً، يتيح لك نمط الجسر استبدال كائن التنفيذ داخل التجريد. الأمر بسيط كتعيين قيمة جديدة لحقل.

بالمناسبة، هذا البند الأخير هو السبب الرئيسي وراء خلط كثير من المطورين بين نمط الجسر ونمط [الاستراتيجية](/ar/design-patterns/strategy). تذكر أن النمط أكثر من مجرد طريقة معينة لهيكلة كلاساتك؛ فهو أيضاً يعبِّر عن القصد والمشكلة التي يعالجها.

## How to Implement

1. حدِّد الأبعاد المتعامدة في كلاساتك. هذه المفاهيم المستقلة يمكن أن تكون: التجريد/المنصة، والمجال/البنية التحتية، والواجهة الأمامية/الخلفية، أو الواجهة/التنفيذ.
2. تعرَّف على العمليات التي يحتاجها العميل وعرِّفها في كلاس التجريد الأساسي.
3. حدِّد العمليات المتاحة على جميع المنصات. أعلِن عن العمليات التي يحتاجها التجريد في واجهة التنفيذ العامة.
4. لجميع المنصات في مجالك، أنشئ كلاسات تنفيذ ملموسة، لكن تأكد من أنها جميعها تتبع واجهة التنفيذ.
5. داخل كلاس التجريد، أضف حقل مرجع لنوع التنفيذ. يُفوِّض التجريد معظم العمل إلى كائن التنفيذ المُشار إليه في ذلك الحقل.
6. إذا كان لديك عدة متغيرات من المنطق عالي المستوى، فأنشئ تجريدات مُحسَّنة لكل متغير بتوسيع كلاس التجريد الأساسي.
7. يجب أن يمرر كود العميل كائن تنفيذ إلى مُنشئ التجريد لربطهما ببعض. بعد ذلك يمكن للعميل نسيان أمر التنفيذ والعمل فقط مع كائن التجريد.

## Pros

* يمكنك إنشاء كلاسات وتطبيقات مستقلة عن المنصة.
* يتعامل كود العميل مع تجريدات عالية المستوى ولا يتعرض لتفاصيل المنصة.
* _مبدأ مفتوح/مغلق_. يمكنك إدخال تجريدات وتنفيذات جديدة بشكل مستقل عن بعضها.
* _مبدأ المسؤولية الواحدة_. يمكنك التركيز على المنطق عالي المستوى في التجريد، وعلى تفاصيل المنصة في التنفيذ.

## Cons

* قد تجعل الكود أكثر تعقيداً عند تطبيق النمط على كلاس متماسك للغاية.

## Relations with Other Patterns

* عادةً يُصمَّم [الجسر](/ar/design-patterns/bridge) مسبقاً، مما يتيح لك تطوير أجزاء التطبيق بشكل مستقل عن بعضها. في المقابل، يُستخدم [المحوِّل](/ar/design-patterns/adapter) عادةً مع تطبيق قائم لجعل بعض الكلاسات غير المتوافقة تعمل معاً بشكل جيد.
* يمتلك [الجسر](/ar/design-patterns/bridge) و[الحالة](/ar/design-patterns/state) و[الاستراتيجية](/ar/design-patterns/strategy) (وإلى حد ما [المحوِّل](/ar/design-patterns/adapter)) هياكل متشابهة جداً. في الواقع، تستند جميع هذه الأنماط إلى التركيب، وهو تفويض العمل إلى كائنات أخرى. غير أنها جميعاً تحل مشاكل مختلفة. النمط ليس مجرد وصفة لهيكلة الكود بطريقة معينة؛ فهو أيضاً يُوصل إلى المطورين الآخرين المشكلة التي يحلها.
* يمكنك استخدام [المصنع التجريدي](/ar/design-patterns/abstract-factory) جنباً إلى جنب مع [الجسر](/ar/design-patterns/bridge). هذا الترادف مفيد عندما يمكن لبعض التجريدات المُعرَّفة بواسطة _الجسر_ أن تعمل فقط مع تنفيذات محددة. في هذه الحالة، يمكن للمصنع التجريدي تغليف هذه العلاقات وإخفاء التعقيد عن كود العميل.
* يمكنك دمج [المنشئ](/ar/design-patterns/builder) مع [الجسر](/ar/design-patterns/bridge): يؤدي كلاس المخرج دور التجريد، بينما تعمل المنشئات المختلفة كتنفيذات.
## Relations

**Related patterns**

- [المهايئ (Adapter)](/ar/design-patterns/adapter.md)
- [الحالة](/ar/design-patterns/state.md)
- [الاستراتيجية](/ar/design-patterns/strategy.md)
- [المصنع المجرد (Abstract Factory)](/ar/design-patterns/abstract-factory.md)
- [البنّاء](/ar/design-patterns/builder.md)

## Code Examples

### java

```java
package refactoring_guru.bridge.example.devices;

public interface Device {
    boolean isEnabled();

    void enable();

    void disable();

    int getVolume();

    void setVolume(int percent);

    int getChannel();

    void setChannel(int channel);

    void printStatus();
}

package refactoring_guru.bridge.example.devices;

public class Radio implements Device {
    private boolean on = false;
    private int volume = 30;
    private int channel = 1;

    @Override
    public boolean isEnabled() {
        return on;
    }

    @Override
    public void enable() {
        on = true;
    }

    @Override
    public void disable() {
        on = false;
    }

    @Override
    public int getVolume() {
        return volume;
    }

    @Override
    public void setVolume(int volume) {
        if (volume > 100) {
            this.volume = 100;
        } else if (volume < 0) {
            this.volume = 0;
        } else {
            this.volume = volume;
        }
    }

    @Override
    public int getChannel() {
        return channel;
    }

    @Override
    public void setChannel(int channel) {
        this.channel = channel;
    }

    @Override
    public void printStatus() {
        System.out.println("------------------------------------");
        System.out.println("| I'm radio.");
        System.out.println("| I'm " + (on ? "enabled" : "disabled"));
        System.out.println("| Current volume is " + volume + "%");
        System.out.println("| Current channel is " + channel);
        System.out.println("------------------------------------\n");
    }
}

package refactoring_guru.bridge.example.devices;

public class Tv implements Device {
    private boolean on = false;
    private int volume = 30;
    private int channel = 1;

    @Override
    public boolean isEnabled() {
        return on;
    }

    @Override
    public void enable() {
        on = true;
    }

    @Override
    public void disable() {
        on = false;
    }

    @Override
    public int getVolume() {
        return volume;
    }

    @Override
    public void setVolume(int volume) {
        if (volume > 100) {
            this.volume = 100;
        } else if (volume < 0) {
            this.volume = 0;
        } else {
            this.volume = volume;
        }
    }

    @Override
    public int getChannel() {
        return channel;
    }

    @Override
    public void setChannel(int channel) {
        this.channel = channel;
    }

    @Override
    public void printStatus() {
        System.out.println("------------------------------------");
        System.out.println("| I'm TV set.");
        System.out.println("| I'm " + (on ? "enabled" : "disabled"));
        System.out.println("| Current volume is " + volume + "%");
        System.out.println("| Current channel is " + channel);
        System.out.println("------------------------------------\n");
    }
}

package refactoring_guru.bridge.example.remotes;

public interface Remote {
    void power();

    void volumeDown();

    void volumeUp();

    void channelDown();

    void channelUp();
}

package refactoring_guru.bridge.example.remotes;

import refactoring_guru.bridge.example.devices.Device;

public class BasicRemote implements Remote {
    protected Device device;

    public BasicRemote() {}

    public BasicRemote(Device device) {
        this.device = device;
    }

    @Override
    public void power() {
        System.out.println("Remote: power toggle");
        if (device.isEnabled()) {
            device.disable();
        } else {
            device.enable();
        }
    }

    @Override
    public void volumeDown() {
        System.out.println("Remote: volume down");
        device.setVolume(device.getVolume() - 10);
    }

    @Override
    public void volumeUp() {
        System.out.println("Remote: volume up");
        device.setVolume(device.getVolume() + 10);
    }

    @Override
    public void channelDown() {
        System.out.println("Remote: channel down");
        device.setChannel(device.getChannel() - 1);
    }

    @Override
    public void channelUp() {
        System.out.println("Remote: channel up");
        device.setChannel(device.getChannel() + 1);
    }
}

package refactoring_guru.bridge.example.remotes;

import refactoring_guru.bridge.example.devices.Device;

public class AdvancedRemote extends BasicRemote {

    public AdvancedRemote(Device device) {
        super.device = device;
    }

    public void mute() {
        System.out.println("Remote: mute");
        device.setVolume(0);
    }
}

package refactoring_guru.bridge.example;

import refactoring_guru.bridge.example.devices.Device;
import refactoring_guru.bridge.example.devices.Radio;
import refactoring_guru.bridge.example.devices.Tv;
import refactoring_guru.bridge.example.remotes.AdvancedRemote;
import refactoring_guru.bridge.example.remotes.BasicRemote;

public class Demo {
    public static void main(String[] args) {
        testDevice(new Tv());
        testDevice(new Radio());
    }

    public static void testDevice(Device device) {
        System.out.println("Tests with basic remote.");
        BasicRemote basicRemote = new BasicRemote(device);
        basicRemote.power();
        device.printStatus();

        System.out.println("Tests with advanced remote.");
        AdvancedRemote advancedRemote = new AdvancedRemote(device);
        advancedRemote.power();
        advancedRemote.mute();
        device.printStatus();
    }
}

Tests with basic remote.
Remote: power toggle
------------------------------------
| I'm TV set.
| I'm enabled
| Current volume is 30%
| Current channel is 1
------------------------------------

Tests with advanced remote.
Remote: power toggle
Remote: mute
------------------------------------
| I'm TV set.
| I'm disabled
| Current volume is 0%
| Current channel is 1
------------------------------------

Tests with basic remote.
Remote: power toggle
------------------------------------
| I'm radio.
| I'm enabled
| Current volume is 30%
| Current channel is 1
------------------------------------

Tests with advanced remote.
Remote: power toggle
Remote: mute
------------------------------------
| I'm radio.
| I'm disabled
| Current volume is 0%
| Current channel is 1
------------------------------------
```

### csharp

```csharp
using System;

namespace RefactoringGuru.DesignPatterns.Bridge.Conceptual
{
    // يُعرِّف التجريد واجهةً للجزء "التحكمي" من التسلسلين الهرميين للكلاسات.
    // ويحتفظ بمرجع لكائن من تسلسل التنفيذ الهرمي ويُفوِّض
    // كل العمل الفعلي لهذا الكائن.
    class Abstraction
    {
        protected IImplementation _implementation;
		
        public Abstraction(IImplementation implementation)
        {
            this._implementation = implementation;
        }
		
        public virtual string Operation()
        {
            return "Abstract: Base operation with:\n" + 
                _implementation.OperationImplementation();
        }
    }

    // يمكنك توسيع التجريد دون تغيير كلاسات التنفيذ.
    class ExtendedAbstraction : Abstraction
    {
        public ExtendedAbstraction(IImplementation implementation) : base(implementation)
        {
		}
		
        public override string Operation()
        {
            return "ExtendedAbstraction: Extended operation with:\n" +
                base._implementation.OperationImplementation();
        }
    }

    // يُعرِّف التنفيذ الواجهةَ لجميع كلاسات التنفيذ.
    // ولا يلزم أن تتطابق مع واجهة التجريد. في الواقع، قد
    // تكون الواجهتان مختلفتين تماماً. عادةً توفر واجهة التنفيذ
    // عمليات أساسية فقط، بينما يُعرِّف التجريد عمليات أعلى مستوى
    // بناءً على تلك العمليات الأساسية.
    public interface IImplementation
    {
        string OperationImplementation();
    }

    // كل تنفيذ ملموس يتوافق مع منصة محددة ويُنفِّذ واجهة التنفيذ
    // باستخدام واجهة برمجة التطبيقات الخاصة بتلك المنصة.
    class ConcreteImplementationA : IImplementation
    {
        public string OperationImplementation()
        {
            return "ConcreteImplementationA: The result in platform A.\n";
        }
    }

    class ConcreteImplementationB : IImplementation
    {
        public string OperationImplementation()
        {
            return "ConcreteImplementationB: The result in platform B.\n";
        }
    }

    class Client
    {
        // باستثناء مرحلة التهيئة، حيث يرتبط كائن التجريد بكائن تنفيذ محدد،
        // يجب أن يعتمد كود العميل فقط على كلاس التجريد. وبهذه الطريقة
        // يمكن لكود العميل دعم أي تركيبة من التجريد والتنفيذ.
        public void ClientCode(Abstraction abstraction)
        {
            Console.Write(abstraction.Operation());
        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            Client client = new Client();

            Abstraction abstraction;
            // يجب أن يتمكن كود العميل من العمل مع أي تركيبة
            // مُهيَّأة مسبقاً من التجريد والتنفيذ.
            abstraction = new Abstraction(new ConcreteImplementationA());
            client.ClientCode(abstraction);
            
            Console.WriteLine();
            
            abstraction = new ExtendedAbstraction(new ConcreteImplementationB());
            client.ClientCode(abstraction);
        }
    }
}

Abstract: Base operation with:
ConcreteImplementationA: The result in platform A.

ExtendedAbstraction: Extended operation with:
ConcreteImplementationA: The result in platform B.
```

### cpp

```cpp
/**
 * يُعرِّف التنفيذ الواجهةَ لجميع كلاسات التنفيذ. ولا يلزم أن
 * تتطابق مع واجهة التجريد. في الواقع، قد تكون الواجهتان مختلفتين تماماً.
 * عادةً توفر واجهة التنفيذ عمليات أساسية فقط، بينما يُعرِّف التجريد
 * عمليات أعلى مستوى بناءً على تلك العمليات الأساسية.
 */

class Implementation {
 public:
  virtual ~Implementation() {}
  virtual std::string OperationImplementation() const = 0;
};

/**
 * كل تنفيذ ملموس يتوافق مع منصة محددة ويُنفِّذ واجهة التنفيذ
 * باستخدام واجهة برمجة التطبيقات الخاصة بتلك المنصة.
 */
class ConcreteImplementationA : public Implementation {
 public:
  std::string OperationImplementation() const override {
    return "ConcreteImplementationA: Here's the result on the platform A.\n";
  }
};
class ConcreteImplementationB : public Implementation {
 public:
  std::string OperationImplementation() const override {
    return "ConcreteImplementationB: Here's the result on the platform B.\n";
  }
};

/**
 * يُعرِّف التجريد واجهةً للجزء "التحكمي" من التسلسلين الهرميين للكلاسات.
 * ويحتفظ بمرجع لكائن من تسلسل التنفيذ الهرمي ويُفوِّض كل العمل الفعلي
 * لهذا الكائن.
 */

class Abstraction {
  /**
   * @var Implementation
   */
 protected:
  Implementation* implementation_;

 public:
  Abstraction(Implementation* implementation) : implementation_(implementation) {
  }

  virtual ~Abstraction() {
  }

  virtual std::string Operation() const {
    return "Abstraction: Base operation with:\n" +
           this->implementation_->OperationImplementation();
  }
};
/**
 * يمكنك توسيع التجريد دون تغيير كلاسات التنفيذ.
 */
class ExtendedAbstraction : public Abstraction {
 public:
  ExtendedAbstraction(Implementation* implementation) : Abstraction(implementation) {
  }
  std::string Operation() const override {
    return "ExtendedAbstraction: Extended operation with:\n" +
           this->implementation_->OperationImplementation();
  }
};

/**
 * باستثناء مرحلة التهيئة، حيث يرتبط كائن التجريد بكائن تنفيذ محدد،
 * يجب أن يعتمد كود العميل فقط على كلاس التجريد. وبهذه الطريقة يمكن
 * لكود العميل دعم أي تركيبة من التجريد والتنفيذ.
 */
void ClientCode(const Abstraction& abstraction) {
  // ...
  std::cout << abstraction.Operation();
  // ...
}
/**
 * يجب أن يتمكن كود العميل من العمل مع أي تركيبة مُهيَّأة مسبقاً
 * من التجريد والتنفيذ.
 */

int main() {
  Implementation* implementation = new ConcreteImplementationA;
  Abstraction* abstraction = new Abstraction(implementation);
  ClientCode(*abstraction);
  std::cout << std::endl;
  delete implementation;
  delete abstraction;

  implementation = new ConcreteImplementationB;
  abstraction = new ExtendedAbstraction(implementation);
  ClientCode(*abstraction);

  delete implementation;
  delete abstraction;

  return 0;
}

Abstraction: Base operation with:
ConcreteImplementationA: Here's the result on the platform A.

ExtendedAbstraction: Extended operation with:
ConcreteImplementationB: Here's the result on the platform B.
```

### go

```go
package main

type Computer interface {
	Print()
	SetPrinter(Printer)
}

package main

import "fmt"

type Mac struct {
	printer Printer
}

func (m *Mac) Print() {
	fmt.Println("Print request for mac")
	m.printer.PrintFile()
}

func (m *Mac) SetPrinter(p Printer) {
	m.printer = p
}

package main

import "fmt"

type Windows struct {
	printer Printer
}

func (w *Windows) Print() {
	fmt.Println("Print request for windows")
	w.printer.PrintFile()
}

func (w *Windows) SetPrinter(p Printer) {
	w.printer = p
}

package main

type Printer interface {
	PrintFile()
}

package main

import "fmt"

type Epson struct {
}

func (p *Epson) PrintFile() {
	fmt.Println("Printing by a EPSON Printer")
}

package main

import "fmt"

type Hp struct {
}

func (p *Hp) PrintFile() {
	fmt.Println("Printing by a HP Printer")
}

package main

import "fmt"

func main() {

	hpPrinter := &Hp{}
	epsonPrinter := &Epson{}

	macComputer := &Mac{}

	macComputer.SetPrinter(hpPrinter)
	macComputer.Print()
	fmt.Println()

	macComputer.SetPrinter(epsonPrinter)
	macComputer.Print()
	fmt.Println()

	winComputer := &Windows{}

	winComputer.SetPrinter(hpPrinter)
	winComputer.Print()
	fmt.Println()

	winComputer.SetPrinter(epsonPrinter)
	winComputer.Print()
	fmt.Println()
}

Print request for mac
Printing by a HP Printer

Print request for mac
Printing by a EPSON Printer

Print request for windows
Printing by a HP Printer

Print request for windows
```

### php

```php
<?php

namespace RefactoringGuru\Bridge\Conceptual;

/**
 * يُعرِّف التجريد واجهةً للجزء "التحكمي" من التسلسلين الهرميين للكلاسات.
 * ويحتفظ بمرجع لكائن من تسلسل التنفيذ الهرمي ويُفوِّض كل العمل الفعلي لهذا الكائن.
 */
class Abstraction
{
    /**
     * @var Implementation
     */
    protected $implementation;

    public function __construct(Implementation $implementation)
    {
        $this->implementation = $implementation;
    }

    public function operation(): string
    {
        return "Abstraction: Base operation with:\n" .
            $this->implementation->operationImplementation();
    }
}

/**
 * يمكنك توسيع التجريد دون تغيير كلاسات التنفيذ.
 */
class ExtendedAbstraction extends Abstraction
{
    public function operation(): string
    {
        return "ExtendedAbstraction: Extended operation with:\n" .
            $this->implementation->operationImplementation();
    }
}

/**
 * يُعرِّف التنفيذ الواجهةَ لجميع كلاسات التنفيذ. ولا يلزم
 * أن تتطابق مع واجهة التجريد. في الواقع، قد تكون الواجهتان مختلفتين تماماً.
 * عادةً توفر واجهة التنفيذ عمليات أساسية فقط، بينما يُعرِّف التجريد
 * عمليات أعلى مستوى بناءً على تلك العمليات الأساسية.
 */
interface Implementation
{
    public function operationImplementation(): string;
}

/**
 * كل تنفيذ ملموس يتوافق مع منصة محددة ويُنفِّذ واجهة التنفيذ
 * باستخدام واجهة برمجة التطبيقات الخاصة بتلك المنصة.
 */
class ConcreteImplementationA implements Implementation
{
    public function operationImplementation(): string
    {
        return "ConcreteImplementationA: Here's the result on the platform A.\n";
    }
}

class ConcreteImplementationB implements Implementation
{
    public function operationImplementation(): string
    {
        return "ConcreteImplementationB: Here's the result on the platform B.\n";
    }
}

/**
 * باستثناء مرحلة التهيئة، حيث يرتبط كائن التجريد بكائن تنفيذ محدد،
 * يجب أن يعتمد كود العميل فقط على كلاس التجريد. وبهذه الطريقة
 * يمكن لكود العميل دعم أي تركيبة من التجريد والتنفيذ.
 */
function clientCode(Abstraction $abstraction)
{
    // ...

    echo $abstraction->operation();

    // ...
}

/**
 * يجب أن يتمكن كود العميل من العمل مع أي تركيبة مُهيَّأة مسبقاً
 * من التجريد والتنفيذ.
 */
$implementation = new ConcreteImplementationA();
$abstraction = new Abstraction($implementation);
clientCode($abstraction);

echo "\n";

$implementation = new ConcreteImplementationB();
$abstraction = new ExtendedAbstraction($implementation);
clientCode($abstraction);

Abstraction: Base operation with:
ConcreteImplementationA: Here's the result on the platform A.

ExtendedAbstraction: Extended operation with:
ConcreteImplementationB: Here's the result on the platform B.

<?php

namespace RefactoringGuru\Bridge\RealWorld;

/**
 * التجريد.
 */
abstract class Page
{
    /**
     * @var Renderer
     */
    protected $renderer;

    /**
     * عادةً يُهيَّأ التجريد بأحد كائنات التنفيذ.
     */
    public function __construct(Renderer $renderer)
    {
        $this->renderer = $renderer;
    }

    /**
     * يتيح نمط الجسر استبدال كائن التنفيذ المرتبط ديناميكياً.
     */
    public function changeRenderer(Renderer $renderer): void
    {
        $this->renderer = $renderer;
    }

    /**
     * يظل سلوك "view" مجرداً لأنه لا يمكن توفيره إلا بواسطة
     * كلاسات التجريد الملموسة.
     */
    abstract public function view(): string;
}

/**
 * يمثل هذا التجريد الملموس صفحة بسيطة.
 */
class SimplePage extends Page
{
    protected $title;
    protected $content;

    public function __construct(Renderer $renderer, string $title, string $content)
    {
        parent::__construct($renderer);
        $this->title = $title;
        $this->content = $content;
    }

    public function view(): string
    {
        return $this->renderer->renderParts([
            $this->renderer->renderHeader(),
            $this->renderer->renderTitle($this->title),
            $this->renderer->renderTextBlock($this->content),
            $this->renderer->renderFooter()
        ]);
    }
}

/**
 * يمثل هذا التجريد الملموس صفحة أكثر تعقيداً.
 */
class ProductPage extends Page
{
    protected $product;

    public function __construct(Renderer $renderer, Product $product)
    {
        parent::__construct($renderer);
        $this->product = $product;
    }

    public function view(): string
    {
        return $this->renderer->renderParts([
            $this->renderer->renderHeader(),
            $this->renderer->renderTitle($this->product->getTitle()),
            $this->renderer->renderTextBlock($this->product->getDescription()),
            $this->renderer->renderImage($this->product->getImage()),
            $this->renderer->renderTextBlock('$' . number_format($this->product->getPrice(), 2)),
            $this->renderer->renderLink("/cart/add/" . $this->product->getId(), "Add to cart"),
            $this->renderer->renderFooter()
        ]);
    }
}

/**
 * كلاس مساعد لكلاس ProductPage.
 */
class Product
{
    private $id, $title, $description, $image, $price;

    public function __construct(
        string $id,
        string $title,
        string $description,
        string $image,
        float $price
    ) {
        $this->id = $id;
        $this->title = $title;
        $this->description = $description;
        $this->image = $image;
        $this->price = $price;
    }

    public function getId(): string
    {
        return $this->id;
    }

    public function getTitle(): string
    {
        return $this->title;
    }

    public function getDescription(): string
    {
        return $this->description;
    }

    public function getImage(): string
    {
        return $this->image;
    }

    public function getPrice(): float
    {
        return $this->price;
    }
}


/**
 * يُعلن التنفيذ عن مجموعة من الأساليب "الحقيقية"، "الداخلية"، "للمنصة".
 *
 * في هذه الحالة، يُدرج التنفيذ أساليب العرض التي يمكن استخدامها لتأليف
 * أي صفحة ويب. قد تستخدم التجريدات المختلفة أساليب مختلفة من التنفيذ.
 */
interface Renderer
{
    public function renderTitle(string $title): string;

    public function renderTextBlock(string $text): string;

    public function renderImage(string $url): string;

    public function renderLink(string $url, string $title): string;

    public function renderHeader(): string;

    public function renderFooter(): string;

    public function renderParts(array $parts): string;
}

/**
 * يُقدِّم هذا التنفيذ الملموس صفحة الويب بصيغة HTML.
 */
class HTMLRenderer implements Renderer
{
    public function renderTitle(string $title): string
    {
        return "<h1>$title</h1>";
    }

    public function renderTextBlock(string $text): string
    {
        return "<div class='text'>$text</div>";
    }

    public function renderImage(string $url): string
    {
        return "<img src='$url'>";
    }

    public function renderLink(string $url, string $title): string
    {
        return "<a href='$url'>$title</a>";
    }

    public function renderHeader(): string
    {
        return "<html><body>";
    }

    public function renderFooter(): string
    {
        return "</body></html>";
    }

    public function renderParts(array $parts): string
    {
        return implode("\n", $parts);
    }
}

/**
 * يُقدِّم هذا التنفيذ الملموس صفحة الويب كسلاسل JSON.
 */
class JsonRenderer implements Renderer
{
    public function renderTitle(string $title): string
    {
        return '"title": "' . $title . '"';
    }

    public function renderTextBlock(string $text): string
    {
        return '"text": "' . $text . '"';
    }

    public function renderImage(string $url): string
    {
        return '"img": "' . $url . '"';
    }

    public function renderLink(string $url, string $title): string
    {
        return '"link": {"href": "' . $url . '", "title": "' . $title . '"}';
    }

    public function renderHeader(): string
    {
        return '';
    }

    public function renderFooter(): string
    {
        return '';
    }

    public function renderParts(array $parts): string
    {
        return "{\n" . implode(",\n", array_filter($parts)) . "\n}";
    }
}

/**
 * يتعامل كود العميل عادةً مع كائنات التجريد فقط.
 */
function clientCode(Page $page)
{
    // ...

    echo $page->view();

    // ...
}

/**
 * يمكن تنفيذ كود العميل مع أي تركيبة مُهيَّأة مسبقاً
 * من التجريد والتنفيذ.
 */
$HTMLRenderer = new HTMLRenderer();
$JSONRenderer = new JsonRenderer();

$page = new SimplePage($HTMLRenderer, "Home", "Welcome to our website!");
echo "HTML view of a simple content page:\n";
clientCode($page);
echo "\n\n";

/**
 * يمكن للتجريد تغيير التنفيذ المرتبط في وقت التشغيل إذا لزم الأمر.
 */
$page->changeRenderer($JSONRenderer);
echo "JSON view of a simple content page, rendered with the same client code:\n";
clientCode($page);
echo "\n\n";


$product = new Product(
    "123",
    "Star Wars, episode1",
    "A long time ago in a galaxy far, far away...",
    "/images/star-wars.jpeg",
    39.95
);

$page = new ProductPage($HTMLRenderer, $product);
echo "HTML view of a product page, same client code:\n";
clientCode($page);
echo "\n\n";

$page->changeRenderer($JSONRenderer);
echo "JSON view of a simple content page, with the same client code:\n";
clientCode($page);

HTML view of a simple content page:
<html><body>
<h1>Home</h1>
<div class='text'>Welcome to our website!</div>
</body></html>

JSON view of a simple content page, rendered with the same client code:
{
"title": "Home",
"text": "Welcome to our website!"
}

HTML view of a product page, same client code:
<html><body>
<h1>Star Wars, episode1</h1>
<div class='text'>A long time ago in a galaxy far, far away...</div>
<img src='/images/star-wars.jpeg'>
<a href='/cart/add/123'>Add to cart</a>
</body></html>

JSON view of a simple content page, with the same client code:
{
"title": "Star Wars, episode1",
"text": "A long time ago in a galaxy far, far away...",
"img": "/images/star-wars.jpeg",
"link": {"href": "/cart/add/123", "title": "Add to cart"}
}
```

### python

```python
from __future__ import annotations
from abc import ABC, abstractmethod


class Abstraction:
    """
    يُعرِّف التجريد واجهةً للجزء "التحكمي" من التسلسلين الهرميين للكلاسات.
    ويحتفظ بمرجع لكائن من تسلسل التنفيذ الهرمي ويُفوِّض كل العمل الفعلي لهذا الكائن.
    """

    def __init__(self, implementation: Implementation) -> None:
        self.implementation = implementation

    def operation(self) -> str:
        return (f"Abstraction: Base operation with:\n"
                f"{self.implementation.operation_implementation()}")


class ExtendedAbstraction(Abstraction):
    """
    يمكنك توسيع التجريد دون تغيير كلاسات التنفيذ.
    """

    def operation(self) -> str:
        return (f"ExtendedAbstraction: Extended operation with:\n"
                f"{self.implementation.operation_implementation()}")


class Implementation(ABC):
    """
    يُعرِّف التنفيذ الواجهةَ لجميع كلاسات التنفيذ. ولا يلزم أن تتطابق مع
    واجهة التجريد. في الواقع، قد تكون الواجهتان مختلفتين تماماً. عادةً توفر
    واجهة التنفيذ عمليات أساسية فقط، بينما يُعرِّف التجريد عمليات أعلى مستوى
    بناءً على تلك العمليات الأساسية.
    """

    @abstractmethod
    def operation_implementation(self) -> str:
        pass


"""
كل تنفيذ ملموس يتوافق مع منصة محددة ويُنفِّذ واجهة التنفيذ
باستخدام واجهة برمجة التطبيقات الخاصة بتلك المنصة.
"""


class ConcreteImplementationA(Implementation):
    def operation_implementation(self) -> str:
        return "ConcreteImplementationA: Here's the result on the platform A."


class ConcreteImplementationB(Implementation):
    def operation_implementation(self) -> str:
        return "ConcreteImplementationB: Here's the result on the platform B."


def client_code(abstraction: Abstraction) -> None:
    """
    باستثناء مرحلة التهيئة، حيث يرتبط كائن التجريد بكائن تنفيذ محدد،
    يجب أن يعتمد كود العميل فقط على كلاس التجريد. وبهذه الطريقة
    يمكن لكود العميل دعم أي تركيبة من التجريد والتنفيذ.
    """

    # ...

    print(abstraction.operation(), end="")

    # ...


if __name__ == "__main__":
    """
    يجب أن يتمكن كود العميل من العمل مع أي تركيبة مُهيَّأة مسبقاً
    من التجريد والتنفيذ.
    """

    implementation = ConcreteImplementationA()
    abstraction = Abstraction(implementation)
    client_code(abstraction)

    print("\n")

    implementation = ConcreteImplementationB()
    abstraction = ExtendedAbstraction(implementation)
    client_code(abstraction)

Abstraction: Base operation with:
ConcreteImplementationA: Here's the result on the platform A.

ExtendedAbstraction: Extended operation with:
ConcreteImplementationB: Here's the result on the platform B.
```

### ruby

```ruby
# يُعرِّف التجريد واجهةً للجزء "التحكمي" من التسلسلين الهرميين للكلاسات.
# ويحتفظ بمرجع لكائن من تسلسل التنفيذ الهرمي ويُفوِّض كل العمل الفعلي لهذا الكائن.
class Abstraction
  # @param [Implementation] implementation
  def initialize(implementation)
    @implementation = implementation
  end

  # @return [String]
  def operation
    "Abstraction: Base operation with:\n"\
    "#{@implementation.operation_implementation}"
  end
end

# يمكنك توسيع التجريد دون تغيير كلاسات التنفيذ.
class ExtendedAbstraction < Abstraction
  # @return [String]
  def operation
    "ExtendedAbstraction: Extended operation with:\n"\
    "#{@implementation.operation_implementation}"
  end
end

# يُعرِّف التنفيذ الواجهةَ لجميع كلاسات التنفيذ. ولا يلزم أن تتطابق مع واجهة
# التجريد. في الواقع، قد تكون الواجهتان مختلفتين تماماً. عادةً توفر واجهة التنفيذ
# عمليات أساسية فقط، بينما يُعرِّف التجريد عمليات أعلى مستوى بناءً على تلك العمليات.
class Implementation
  # @abstract
  #
  # @return [String]
  def operation_implementation
    raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
  end
end

# كل تنفيذ ملموس يتوافق مع منصة محددة ويُنفِّذ واجهة التنفيذ
# باستخدام واجهة برمجة التطبيقات الخاصة بتلك المنصة.
class ConcreteImplementationA < Implementation
  # @return [String]
  def operation_implementation
    'ConcreteImplementationA: Here\'s the result on the platform A.'
  end
end

class ConcreteImplementationB < Implementation
  # @return [String]
  def operation_implementation
    'ConcreteImplementationB: Here\'s the result on the platform B.'
  end
end

# باستثناء مرحلة التهيئة، حيث يرتبط كائن التجريد بكائن تنفيذ محدد،
# يجب أن يعتمد كود العميل فقط على كلاس التجريد. وبهذه الطريقة
# يمكن لكود العميل دعم أي تركيبة من التجريد والتنفيذ.
def client_code(abstraction)
  # ...

  print abstraction.operation

  # ...
end

# يجب أن يتمكن كود العميل من العمل مع أي تركيبة مُهيَّأة مسبقاً
# من التجريد والتنفيذ.

implementation = ConcreteImplementationA.new
abstraction = Abstraction.new(implementation)
client_code(abstraction)

puts "\n\n"

implementation = ConcreteImplementationB.new
abstraction = ExtendedAbstraction.new(implementation)
client_code(abstraction)

Abstraction: Base operation with:
ConcreteImplementationA: Here's the result on the platform A.

ExtendedAbstraction: Extended operation with:
ConcreteImplementationB: Here's the result on the platform B.
```

### rust

```rust
mod advanced;
mod basic;

pub use advanced::AdvancedRemote;
pub use basic::BasicRemote;

use crate::device::Device;

pub trait HasMutableDevice<D: Device> {
    fn device(&mut self) -> &mut D;
}

pub trait Remote<D: Device>: HasMutableDevice<D> {
    fn power(&mut self) {
        println!("Remote: power toggle");
        if self.device().is_enabled() {
            self.device().disable();
        } else {
            self.device().enable();
        }
    }

    fn volume_down(&mut self) {
        println!("Remote: volume down");
        let volume = self.device().volume();
        self.device().set_volume(volume - 10);
    }

    fn volume_up(&mut self) {
        println!("Remote: volume up");
        let volume = self.device().volume();
        self.device().set_volume(volume + 10);
    }

    fn channel_down(&mut self) {
        println!("Remote: channel down");
        let channel = self.device().channel();
        self.device().set_channel(channel - 1);
    }

    fn channel_up(&mut self) {
        println!("Remote: channel up");
        let channel = self.device().channel();
        self.device().set_channel(channel + 1);
    }
}

use crate::device::Device;

use super::{HasMutableDevice, Remote};

pub struct BasicRemote<D: Device> {
    device: D,
}

impl<D: Device> BasicRemote<D> {
    pub fn new(device: D) -> Self {
        Self { device }
    }
}

impl<D: Device> HasMutableDevice<D> for BasicRemote<D> {
    fn device(&mut self) -> &mut D {
        &mut self.device
    }
}

impl<D: Device> Remote<D> for BasicRemote<D> {}

use crate::device::Device;

use super::{HasMutableDevice, Remote};

pub struct AdvancedRemote<D: Device> {
    device: D,
}

impl<D: Device> AdvancedRemote<D> {
    pub fn new(device: D) -> Self {
        Self { device }
    }

    pub fn mute(&mut self) {
        println!("Remote: mute");
        self.device.set_volume(0);
    }
}

impl<D: Device> HasMutableDevice<D> for AdvancedRemote<D> {
    fn device(&mut self) -> &mut D {
        &mut self.device
    }
}

impl<D: Device> Remote<D> for AdvancedRemote<D> {}

mod radio;
mod tv;

pub use radio::Radio;
pub use tv::Tv;

pub trait Device {
    fn is_enabled(&self) -> bool;
    fn enable(&mut self);
    fn disable(&mut self);
    fn volume(&self) -> u8;
    fn set_volume(&mut self, percent: u8);
    fn channel(&self) -> u16;
    fn set_channel(&mut self, channel: u16);
    fn print_status(&self);
}

use super::Device;

#[derive(Clone)]
pub struct Radio {
    on: bool,
    volume: u8,
    channel: u16,
}

impl Default for Radio {
    fn default() -> Self {
        Self {
            on: false,
            volume: 30,
            channel: 1,
        }
    }
}

impl Device for Radio {
    fn is_enabled(&self) -> bool {
        self.on
    }

    fn enable(&mut self) {
        self.on = true;
    }

    fn disable(&mut self) {
        self.on = false;
    }

    fn volume(&self) -> u8 {
        self.volume
    }

    fn set_volume(&mut self, percent: u8) {
        self.volume = std::cmp::min(percent, 100);
    }

    fn channel(&self) -> u16 {
        self.channel
    }

    fn set_channel(&mut self, channel: u16) {
        self.channel = channel;
    }

    fn print_status(&self) {
        println!("------------------------------------");
        println!("| I'm radio.");
        println!("| I'm {}", if self.on { "enabled" } else { "disabled" });
        println!("| Current volume is {}%", self.volume);
        println!("| Current channel is {}", self.channel);
        println!("------------------------------------\n");
    }
}

use super::Device;

#[derive(Clone)]
pub struct Tv {
    on: bool,
    volume: u8,
    channel: u16,
}

impl Default for Tv {
    fn default() -> Self {
        Self {
            on: false,
            volume: 30,
            channel: 1,
        }
    }
}

impl Device for Tv {
    fn is_enabled(&self) -> bool {
        self.on
    }

    fn enable(&mut self) {
        self.on = true;
    }

    fn disable(&mut self) {
        self.on = false;
    }

    fn volume(&self) -> u8 {
        self.volume
    }

    fn set_volume(&mut self, percent: u8) {
        self.volume = std::cmp::min(percent, 100);
    }

    fn channel(&self) -> u16 {
        self.channel
    }

    fn set_channel(&mut self, channel: u16) {
        self.channel = channel;
    }

    fn print_status(&self) {
        println!("------------------------------------");
        println!("| I'm TV set.");
        println!("| I'm {}", if self.on { "enabled" } else { "disabled" });
        println!("| Current volume is {}%", self.volume);
        println!("| Current channel is {}", self.channel);
        println!("------------------------------------\n");
    }
}

mod device;
mod remotes;

use device::{Device, Radio, Tv};
use remotes::{AdvancedRemote, BasicRemote, HasMutableDevice, Remote};

fn main() {
    test_device(Tv::default());
    test_device(Radio::default());
}

fn test_device(device: impl Device + Clone) {
    println!("Tests with basic remote.");
    let mut basic_remote = BasicRemote::new(device.clone());
    basic_remote.power();
    basic_remote.device().print_status();

    println!("Tests with advanced remote.");
    let mut advanced_remote = AdvancedRemote::new(device);
    advanced_remote.power();
    advanced_remote.mute();
    advanced_remote.device().print_status();
}

Tests with basic remote.
Remote: power toggle
------------------------------------
| I'm TV set.
| I'm enabled
| Current volume is 30%
| Current channel is 1
------------------------------------

Tests with advanced remote.
Remote: power toggle
Remote: mute
------------------------------------
| I'm TV set.
| I'm enabled
| Current volume is 0%
| Current channel is 1
------------------------------------

Tests with basic remote.
Remote: power toggle
------------------------------------
| I'm radio.
| I'm enabled
| Current volume is 30%
| Current channel is 1
------------------------------------

Tests with advanced remote.
Remote: power toggle
Remote: mute
------------------------------------
| I'm radio.
| I'm enabled
| Current volume is 0%
| Current channel is 1
------------------------------------```
```

### swift

```swift
import XCTest

/// يُعرِّف التجريد واجهةً للجزء "التحكمي" من التسلسلين الهرميين للكلاسات.
/// ويحتفظ بمرجع لكائن من تسلسل التنفيذ الهرمي ويُفوِّض كل العمل الفعلي لهذا الكائن.
class Abstraction {

    fileprivate var implementation: Implementation

    init(_ implementation: Implementation) {
        self.implementation = implementation
    }

    func operation() -> String {
        let operation = implementation.operationImplementation()
        return "Abstraction: Base operation with:\n" + operation
    }
}

/// يمكنك توسيع التجريد دون تغيير كلاسات التنفيذ.
class ExtendedAbstraction: Abstraction {

    override func operation() -> String {
        let operation = implementation.operationImplementation()
        return "ExtendedAbstraction: Extended operation with:\n" + operation
    }
}

/// يُعرِّف التنفيذ الواجهةَ لجميع كلاسات التنفيذ. ولا يلزم أن تتطابق مع واجهة
/// التجريد. في الواقع، قد تكون الواجهتان مختلفتين تماماً. عادةً توفر واجهة التنفيذ
/// عمليات أساسية فقط، بينما يُعرِّف التجريد عمليات أعلى مستوى بناءً على تلك العمليات.
protocol Implementation {

    func operationImplementation() -> String
}

/// كل تنفيذ ملموس يتوافق مع منصة محددة ويُنفِّذ واجهة التنفيذ
/// باستخدام واجهة برمجة التطبيقات الخاصة بتلك المنصة.
class ConcreteImplementationA: Implementation {

    func operationImplementation() -> String {
        return "ConcreteImplementationA: Here's the result on the platform A.\n"
    }
}

class ConcreteImplementationB: Implementation {

    func operationImplementation() -> String {
        return "ConcreteImplementationB: Here's the result on the platform B\n"
    }
}

/// باستثناء مرحلة التهيئة، حيث يرتبط كائن التجريد بكائن تنفيذ محدد،
/// يجب أن يعتمد كود العميل فقط على كلاس التجريد. وبهذه الطريقة
/// يمكن لكود العميل دعم أي تركيبة من التجريد والتنفيذ.
class Client {
    // ...
    static func someClientCode(abstraction: Abstraction) {
        print(abstraction.operation())
    }
    // ...
}

/// لنرَ كيف يعمل كل شيء معاً.
class BridgeConceptual: XCTestCase {

    func testBridgeConceptual() {
        // يجب أن يتمكن كود العميل من العمل مع أي تركيبة مُهيَّأة
        // مسبقاً من التجريد والتنفيذ.
        let implementation = ConcreteImplementationA()
        Client.someClientCode(abstraction: Abstraction(implementation))

        let concreteImplementation = ConcreteImplementationB()
        Client.someClientCode(abstraction: ExtendedAbstraction(concreteImplementation))
    }
}

Abstraction: Base operation with:
ConcreteImplementationA: Here's the result on the platform A

ExtendedAbstraction: Extended operation with:
ConcreteImplementationB: Here's the result on the platform B

import XCTest

private class BridgeRealWorld: XCTestCase {

    func testBridgeRealWorld() {

        print("Client: Pushing Photo View Controller...")
        push(PhotoViewController())

        print()

        print("Client: Pushing Feed View Controller...")
        push(FeedViewController())
    }

    func push(_ container: SharingSupportable) {

        let instagram = InstagramSharingService()
        let facebook = FaceBookSharingService()

        container.accept(service: instagram)
        container.update(content: foodModel)

        container.accept(service: facebook)
        container.update(content: foodModel)
    }

    var foodModel: Content {
        return FoodDomainModel(title: "This food is so various and delicious!",
                               images: [UIImage(), UIImage()],
                               calories: 47)
    }
}

private protocol SharingSupportable {

    /// التجريد
    func accept(service: SharingService)

    func update(content: Content)
}

class BaseViewController: UIViewController, SharingSupportable {

    fileprivate var shareService: SharingService?

    func update(content: Content) {
        /// ...تحديث واجهة المستخدم وعرض المحتوى...
        /// ...
        /// ... ثم سيختار المستخدم محتوى ويُشغِّل حدثاً
        print("\(description): User selected a \(content) to share")
        /// ...
        shareService?.share(content: content)
    }

    func accept(service: SharingService) {
        shareService = service
    }
}

class PhotoViewController: BaseViewController {

    /// واجهة مستخدم وميزات مخصصة

    override var description: String {
        return "PhotoViewController"
    }
}

class FeedViewController: BaseViewController {

    /// واجهة مستخدم وميزات مخصصة

    override var description: String {
        return "FeedViewController"
    }
}

protocol SharingService {

    /// التنفيذ
    func share(content: Content)
}

class FaceBookSharingService: SharingService {

    func share(content: Content) {

        /// استخدم FaceBook API لمشاركة المحتوى
        print("Service: \(content) was posted to the Facebook")
    }
}

class InstagramSharingService: SharingService {

    func share(content: Content) {

        /// استخدم Instagram API لمشاركة المحتوى
        print("Service: \(content) was posted to the Instagram", terminator: "\n\n")
    }
}

protocol Content: CustomStringConvertible {

    var title: String { get }
    var images: [UIImage] { get }
}

struct FoodDomainModel: Content {

    var title: String
    var images: [UIImage]
    var calories: Int

    var description: String {
        return "Food Model"
    }
}

Client: Pushing Photo View Controller...
PhotoViewController: User selected a Food Model to share
Service: Food Model was posted to the Instagram

PhotoViewController: User selected a Food Model to share
Service: Food Model was posted to the Facebook

Client: Pushing Feed View Controller...
FeedViewController: User selected a Food Model to share
Service: Food Model was posted to the Instagram

FeedViewController: User selected a Food Model to share
Service: Food Model was posted to the Facebook
```

### typescript

```typescript
/**
 * يُعرِّف التجريد واجهةً للجزء "التحكمي" من التسلسلين الهرميين للكلاسات.
 * ويحتفظ بمرجع لكائن من تسلسل التنفيذ الهرمي ويُفوِّض كل العمل الفعلي لهذا الكائن.
 */
class Abstraction {
    protected implementation: Implementation;

    constructor(implementation: Implementation) {
        this.implementation = implementation;
    }

    public operation(): string {
        const result = this.implementation.operationImplementation();
        return `Abstraction: Base operation with:\n${result}`;
    }
}

/**
 * يمكنك توسيع التجريد دون تغيير كلاسات التنفيذ.
 */
class ExtendedAbstraction extends Abstraction {
    public operation(): string {
        const result = this.implementation.operationImplementation();
        return `ExtendedAbstraction: Extended operation with:\n${result}`;
    }
}

/**
 * يُعرِّف التنفيذ الواجهةَ لجميع كلاسات التنفيذ. ولا يلزم أن تتطابق مع
 * واجهة التجريد. في الواقع، قد تكون الواجهتان مختلفتين تماماً. عادةً توفر
 * واجهة التنفيذ عمليات أساسية فقط، بينما يُعرِّف التجريد عمليات أعلى مستوى
 * بناءً على تلك العمليات الأساسية.
 */
interface Implementation {
    operationImplementation(): string;
}

/**
 * كل تنفيذ ملموس يتوافق مع منصة محددة ويُنفِّذ واجهة التنفيذ
 * باستخدام واجهة برمجة التطبيقات الخاصة بتلك المنصة.
 */
class ConcreteImplementationA implements Implementation {
    public operationImplementation(): string {
        return 'ConcreteImplementationA: Here\'s the result on the platform A.';
    }
}

class ConcreteImplementationB implements Implementation {
    public operationImplementation(): string {
        return 'ConcreteImplementationB: Here\'s the result on the platform B.';
    }
}

/**
 * باستثناء مرحلة التهيئة، حيث يرتبط كائن التجريد بكائن تنفيذ محدد،
 * يجب أن يعتمد كود العميل فقط على كلاس التجريد. وبهذه الطريقة
 * يمكن لكود العميل دعم أي تركيبة من التجريد والتنفيذ.
 */
function clientCode(abstraction: Abstraction) {
    // ..

    console.log(abstraction.operation());

    // ..
}

/**
 * يجب أن يتمكن كود العميل من العمل مع أي تركيبة مُهيَّأة مسبقاً
 * من التجريد والتنفيذ.
 */
let implementation = new ConcreteImplementationA();
let abstraction = new Abstraction(implementation);
clientCode(abstraction);

console.log('');

implementation = new ConcreteImplementationB();
abstraction = new ExtendedAbstraction(implementation);
clientCode(abstraction);

Abstraction: Base operation with:
ConcreteImplementationA: Here's the result on the platform A.

ExtendedAbstraction: Extended operation with:
ConcreteImplementationB: Here's the result on the platform B.
```

