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

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

## Intent

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

## Problem

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

You might make the program too complex by creating a subclass for every possible configuration of an object.

على سبيل المثال، لنفكر في كيفية إنشاء كائن `House`. لبناء منزل بسيط، تحتاج إلى بناء أربعة جدران وأرضية، وتركيب باب، وتركيب زوج من النوافذ، وبناء سقف. لكن ماذا لو أردت منزلًا أكبر وأكثر إضاءةً، مع فناء خلفي ومميزات أخرى (كنظام تدفئة وسباكة وأسلاك كهربائية)؟

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

هناك نهج آخر لا يستلزم تكثير الفئات الفرعية. يمكنك إنشاء مُنشئ ضخم مباشرةً في فئة `House` الأساسية يحتوي على جميع المعاملات الممكنة التي تتحكم في كائن المنزل. وعلى الرغم من أن هذا النهج يُلغي الحاجة إلى الفئات الفرعية فعلًا، فإنه يُفرز مشكلة أخرى.

The constructor with lots of parameters has its downside: not all the parameters are needed at all times.

في معظم الحالات، ستبقى أغلب المعاملات غير مستخدمة، مما يجعل [استدعاءات المُنشئ قبيحةً للغاية](/ar/smells/long-parameter-list). فعلى سبيل المثال، لا يمتلك إلا جزء صغير من المنازل حمامات سباحة، لذا ستكون المعاملات المتعلقة بحمامات السباحة عديمة الفائدة في تسعة أحيان من أصل عشرة.

## Solution

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

The Builder pattern lets you construct complex objects step by step. The Builder doesn’t allow other objects to access the product while it’s being built.

The pattern organizes object construction into a set of steps (`buildWalls`, `buildDoor`, etc.). To create an object, you execute a series of these steps on a builder object. The important part is that you don’t need to call all of the steps. You can call only those steps that are necessary for producing a particular configuration of an object.

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

في هذه الحالة، يمكنك إنشاء عدة فئات بنّاء مختلفة تُطبّق نفس مجموعة خطوات البناء لكن بطريقة مختلفة. ثم يمكنك استخدام هؤلاء البنّاؤين في عملية البناء (أي مجموعة مرتبة من استدعاءات خطوات البناء) لإنتاج أنواع مختلفة من الكائنات.

Different builders execute the same task in various ways.

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

#### المُوجّه

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

The director knows which building steps to execute to get a working product.

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

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

## Structure

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

## Pseudocode

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

The example of step-by-step construction of cars and the user guides that fit those car models.

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

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

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

The final part is fetching the resulting object. A metal car and a paper manual, although related, are still very different things. We can’t place a method for fetching results in the director without coupling the director to concrete product classes. Hence, we obtain the result of the construction from the builder which performed the job.

// استخدام نمط Builder منطقي فقط عندما تكون منتجاتك
// معقدةً جدًا وتتطلب تهيئةً مكثفة. المنتجان
// التاليان مترابطان وإن لم تكن لهما
// واجهة مشتركة.
class Car is
    // يمكن أن تحتوي السيارة على GPS وحاسوب رحلات وعدد
    // من المقاعد. قد تحتوي موديلات مختلفة من السيارات (رياضية، SUV،
    // مكشوفة) على مميزات مختلفة مثبّتة أو
    // مفعّلة.

class Manual is
    // يجب أن تحتوي كل سيارة على دليل مستخدم يتوافق مع
    // تهيئة السيارة ويصف جميع مميزاتها.

// تُحدّد واجهة البنّاء التوابع الخاصة بإنشاء
// الأجزاء المختلفة من كائنات المنتج.
interface Builder is
    method reset()
    method setSeats(...)
    method setEngine(...)
    method setTripComputer(...)
    method setGPS(...)

// تتبع فئات البنّاء المحدد واجهة البنّاء وتوفر
// تطبيقات محددة لخطوات البناء. قد يكون
// لديك عدة تنوعات من البنّاؤين مُطبَّقة بشكل
// مختلف في برنامجك.
class CarBuilder implements Builder is
    private field car:Car

    // يجب أن يحتوي نموذج البنّاء الجديد على كائن منتج
    // فارغ يستخدمه في التجميع اللاحق.
    constructor CarBuilder() is
        this.reset()

    // يُنظّف تابع reset الكائن قيد البناء.
    method reset() is
        this.car = new Car()

    // جميع خطوات الإنتاج تعمل مع نفس نموذج المنتج.
    method setSeats(...) is
        // تحديد عدد المقاعد في السيارة.

    method setEngine(...) is
        // تركيب محرك معين.

    method setTripComputer(...) is
        // تركيب حاسوب رحلات.

    method setGPS(...) is
        // تركيب نظام تحديد المواقع العالمي.

    // من المفترض أن يوفر البنّاؤون المحددون توابعهم الخاصة
    // لاسترداد النتائج. لأن أنواعًا مختلفة من البنّاؤين قد تُنشئ
    // منتجات مختلفة تمامًا لا تتبع جميعها نفس الواجهة.
    // لذلك لا يمكن الإعلان عن هذه التوابع في واجهة البنّاء
    // (على الأقل ليس في لغات البرمجة ذات الأنواع الستاتيكية).
    //
    // عادةً، بعد إعادة النتيجة النهائية إلى العميل، يُتوقع من
    // نموذج البنّاء أن يكون جاهزًا لبدء إنتاج منتج آخر. لهذا
    // السبب من الشائع استدعاء تابع reset في نهاية جسم
    // تابع `getProduct`. ومع ذلك، هذا السلوك
    // ليس إلزاميًا، ويمكنك جعل البنّاء ينتظر
    // استدعاء reset صريحًا من كود العميل قبل التخلص من النتيجة السابقة.
    method getProduct():Car is
        product = this.car
        this.reset()
        return product

// على خلاف أنماط الإنشاء الأخرى، يُتيح لك البنّاء إنشاء
// منتجات لا تتبع الواجهة المشتركة.
class CarManualBuilder implements Builder is
    private field manual:Manual

    constructor CarManualBuilder() is
        this.reset()

    method reset() is
        this.manual = new Manual()

    method setSeats(...) is
        // توثيق مميزات مقاعد السيارة.

    method setEngine(...) is
        // إضافة تعليمات المحرك.

    method setTripComputer(...) is
        // إضافة تعليمات حاسوب الرحلات.

    method setGPS(...) is
        // إضافة تعليمات نظام تحديد المواقع.

    method getProduct():Manual is
        // إعادة الدليل وإعادة تعيين البنّاء.

// المُوجّه مسؤول فقط عن تنفيذ خطوات البناء
// بتسلسل معين. يفيد ذلك عند إنتاج منتجات
// وفق ترتيب أو تهيئة محددة. بالمعنى الدقيق،
// فئة المُوجّه اختيارية، إذ يمكن للعميل التحكم
// في البنّاؤين مباشرةً.
class Director is
    // يعمل المُوجّه مع أي نموذج بنّاء يُمرّره
    // إليه كود العميل. بهذه الطريقة يمكن لكود العميل
    // تغيير النوع النهائي للمنتج المُجمَّع حديثًا.
    // يمكن للمُوجّه بناء عدة تنوعات من المنتج
    // باستخدام نفس خطوات البناء.
    method constructSportsCar(builder: Builder) is
        builder.reset()
        builder.setSeats(2)
        builder.setEngine(new SportEngine())
        builder.setTripComputer(true)
        builder.setGPS(true)

    method constructSUV(builder: Builder) is
        // ...

// يُنشئ كود العميل كائن البنّاء ويُمرّره إلى المُوجّه
// ثم يُطلق عملية البناء. يُسترد
// الناتج النهائي من كائن البنّاء.
class Application is

    method makeCar() is
        director = new Director()

        CarBuilder builder = new CarBuilder()
        director.constructSportsCar(builder)
        Car car = builder.getProduct()

        CarManualBuilder builder = new CarManualBuilder()
        director.constructSportsCar(builder)

        // غالبًا ما يُسترد المنتج النهائي من كائن
        // البنّاء إذ لا يعلم المُوجّه ولا يعتمد على
        // البنّاؤين المحددين والمنتجات.
        Manual manual = builder.getProduct()

## Applicability

استخدم نمط البنّاء للتخلص من «المُنشئ المتتالي».

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

class Pizza {
    Pizza(int size) { ... }
    Pizza(int size, boolean cheese) { ... }
    Pizza(int size, boolean cheese, boolean pepperoni) { ... }
    // ...

Creating such a monster is only possible in languages that support method overloading, such as C# or Java.

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

 استخدم نمط البنّاء عندما تريد أن تتمكن شيفرتك من إنشاء تمثيلات مختلفة لمنتجٍ ما (على سبيل المثال، منازل حجرية ومنازل خشبية).

 يمكن تطبيق نمط البنّاء عندما يتضمّن بناء تمثيلات مختلفة للمنتج خطواتٍ متشابهة لا تختلف إلا في التفاصيل.

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

 استخدم البنّاء لبناء أشجار [Composite](/ar/design-patterns/composite) أو غيرها من الكائنات المعقدة.

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

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

## How to Implement

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

## Pros

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

## Cons

* تزداد التعقيدية الكلية للشيفرة نظرًا لأن النمط يستلزم إنشاء عدة فئات جديدة.

## Relations with Other Patterns

* تبدأ كثير من التصاميم باستخدام [Factory Method](/ar/design-patterns/factory-method) (الأقل تعقيدًا والأكثر قابلية للتخصيص عبر الفئات الفرعية) وتتطور نحو [Abstract Factory](/ar/design-patterns/abstract-factory) أو [Prototype](/ar/design-patterns/prototype) أو [Builder](/ar/design-patterns/builder) (الأكثر مرونةً لكن الأكثر تعقيدًا).
* يُركّز [Builder](/ar/design-patterns/builder) على إنشاء كائنات معقدة خطوةً بخطوة. يتخصص [Abstract Factory](/ar/design-patterns/abstract-factory) في إنشاء عائلات من الكائنات المترابطة. يُعيد _Abstract Factory_ المنتج فورًا، في حين يُتيح لك _Builder_ تنفيذ خطوات بناء إضافية قبل استرداد المنتج.
* يمكنك استخدام [Builder](/ar/design-patterns/builder) عند إنشاء أشجار [Composite](/ar/design-patterns/composite) معقدة لأنك تستطيع برمجة خطوات البناء الخاصة به للعمل بشكل تعاودي.
* يمكنك دمج [Builder](/ar/design-patterns/builder) مع [Bridge](/ar/design-patterns/bridge): تضطلع فئة المُوجّه بدور التجريد، في حين تعمل البنّاؤون المختلفون كتطبيقات.
* يمكن تطبيق [Abstract Factories](/ar/design-patterns/abstract-factory) و[Builders](/ar/design-patterns/builder) و[Prototypes](/ar/design-patterns/prototype) جميعها كـ[Singletons](/ar/design-patterns/singleton).
## Relations

**Related patterns**

- [طريقة المصنع](/ar/design-patterns/factory-method.md)
- [المصنع المجرد (Abstract Factory)](/ar/design-patterns/abstract-factory.md)
- [النموذج الأولي (Prototype)](/ar/design-patterns/prototype.md)
- [المركَّب](/ar/design-patterns/composite.md)
- [الجسر](/ar/design-patterns/bridge.md)
- [Singleton](/ar/design-patterns/singleton.md)

## Code Examples

### java

```java
package refactoring_guru.builder.example.builders;

import refactoring_guru.builder.example.cars.CarType;
import refactoring_guru.builder.example.components.Engine;
import refactoring_guru.builder.example.components.GPSNavigator;
import refactoring_guru.builder.example.components.Transmission;
import refactoring_guru.builder.example.components.TripComputer;

/**
 * تُعرّف واجهة Builder جميع الطرق الممكنة لتهيئة المنتج.
 */
public interface Builder {
    void setCarType(CarType type);
    void setSeats(int seats);
    void setEngine(Engine engine);
    void setTransmission(Transmission transmission);
    void setTripComputer(TripComputer tripComputer);
    void setGPSNavigator(GPSNavigator gpsNavigator);
}

package refactoring_guru.builder.example.builders;

import refactoring_guru.builder.example.cars.Car;
import refactoring_guru.builder.example.cars.CarType;
import refactoring_guru.builder.example.components.Engine;
import refactoring_guru.builder.example.components.GPSNavigator;
import refactoring_guru.builder.example.components.Transmission;
import refactoring_guru.builder.example.components.TripComputer;

/**
 * تُطبّق البنّاؤون المحددون الخطوات المُعرَّفة في الواجهة المشتركة.
 */
public class CarBuilder implements Builder {
    private CarType type;
    private int seats;
    private Engine engine;
    private Transmission transmission;
    private TripComputer tripComputer;
    private GPSNavigator gpsNavigator;

    @Override
    public void setCarType(CarType type) {
        this.type = type;
    }

    @Override
    public void setSeats(int seats) {
        this.seats = seats;
    }

    @Override
    public void setEngine(Engine engine) {
        this.engine = engine;
    }

    @Override
    public void setTransmission(Transmission transmission) {
        this.transmission = transmission;
    }

    @Override
    public void setTripComputer(TripComputer tripComputer) {
        this.tripComputer = tripComputer;
    }

    @Override
    public void setGPSNavigator(GPSNavigator gpsNavigator) {
        this.gpsNavigator = gpsNavigator;
    }

    public Car getResult() {
        return new Car(type, seats, engine, transmission, tripComputer, gpsNavigator);
    }
}

package refactoring_guru.builder.example.builders;

import refactoring_guru.builder.example.cars.Manual;
import refactoring_guru.builder.example.cars.CarType;
import refactoring_guru.builder.example.components.Engine;
import refactoring_guru.builder.example.components.GPSNavigator;
import refactoring_guru.builder.example.components.Transmission;
import refactoring_guru.builder.example.components.TripComputer;

/**
 * على خلاف أنماط الإنشاء الأخرى، يمكن للبنّاء إنشاء منتجات غير مرتبطة
 * لا تشترك في واجهة مشتركة.
 *
 * في هذه الحالة نبني دليل مستخدم للسيارة باستخدام نفس الخطوات
 * التي بنينا بها السيارة. يُتيح ذلك إنتاج أدلة لموديلات سيارات محددة
 * مُهيَّأة بمميزات مختلفة.
 */
public class CarManualBuilder implements Builder{
    private CarType type;
    private int seats;
    private Engine engine;
    private Transmission transmission;
    private TripComputer tripComputer;
    private GPSNavigator gpsNavigator;

    @Override
    public void setCarType(CarType type) {
        this.type = type;
    }

    @Override
    public void setSeats(int seats) {
        this.seats = seats;
    }

    @Override
    public void setEngine(Engine engine) {
        this.engine = engine;
    }

    @Override
    public void setTransmission(Transmission transmission) {
        this.transmission = transmission;
    }

    @Override
    public void setTripComputer(TripComputer tripComputer) {
        this.tripComputer = tripComputer;
    }

    @Override
    public void setGPSNavigator(GPSNavigator gpsNavigator) {
        this.gpsNavigator = gpsNavigator;
    }

    public Manual getResult() {
        return new Manual(type, seats, engine, transmission, tripComputer, gpsNavigator);
    }
}

package refactoring_guru.builder.example.cars;

import refactoring_guru.builder.example.components.Engine;
import refactoring_guru.builder.example.components.GPSNavigator;
import refactoring_guru.builder.example.components.Transmission;
import refactoring_guru.builder.example.components.TripComputer;

/**
 * Car هي فئة المنتج.
 */
public class Car {
    private final CarType carType;
    private final int seats;
    private final Engine engine;
    private final Transmission transmission;
    private final TripComputer tripComputer;
    private final GPSNavigator gpsNavigator;
    private double fuel = 0;

    public Car(CarType carType, int seats, Engine engine, Transmission transmission,
               TripComputer tripComputer, GPSNavigator gpsNavigator) {
        this.carType = carType;
        this.seats = seats;
        this.engine = engine;
        this.transmission = transmission;
        this.tripComputer = tripComputer;
        if (this.tripComputer != null) {
            this.tripComputer.setCar(this);
        }
        this.gpsNavigator = gpsNavigator;
    }

    public CarType getCarType() {
        return carType;
    }

    public double getFuel() {
        return fuel;
    }

    public void setFuel(double fuel) {
        this.fuel = fuel;
    }

    public int getSeats() {
        return seats;
    }

    public Engine getEngine() {
        return engine;
    }

    public Transmission getTransmission() {
        return transmission;
    }

    public TripComputer getTripComputer() {
        return tripComputer;
    }

    public GPSNavigator getGpsNavigator() {
        return gpsNavigator;
    }
}

package refactoring_guru.builder.example.cars;

import refactoring_guru.builder.example.components.Engine;
import refactoring_guru.builder.example.components.GPSNavigator;
import refactoring_guru.builder.example.components.Transmission;
import refactoring_guru.builder.example.components.TripComputer;

/**
 * دليل السيارة منتجٌ آخر. لاحظ أنه لا يرث من نفس الأصل الذي ترث منه Car. ليس بينهما علاقة.
 */
public class Manual {
    private final CarType carType;
    private final int seats;
    private final Engine engine;
    private final Transmission transmission;
    private final TripComputer tripComputer;
    private final GPSNavigator gpsNavigator;

    public Manual(CarType carType, int seats, Engine engine, Transmission transmission,
                  TripComputer tripComputer, GPSNavigator gpsNavigator) {
        this.carType = carType;
        this.seats = seats;
        this.engine = engine;
        this.transmission = transmission;
        this.tripComputer = tripComputer;
        this.gpsNavigator = gpsNavigator;
    }

    public String print() {
        String info = "";
        info += "Type of car: " + carType + "\n";
        info += "Count of seats: " + seats + "\n";
        info += "Engine: volume - " + engine.getVolume() + "; mileage - " + engine.getMileage() + "\n";
        info += "Transmission: " + transmission + "\n";
        if (this.tripComputer != null) {
            info += "Trip Computer: Functional" + "\n";
        } else {
            info += "Trip Computer: N/A" + "\n";
        }
        if (this.gpsNavigator != null) {
            info += "GPS Navigator: Functional" + "\n";
        } else {
            info += "GPS Navigator: N/A" + "\n";
        }
        return info;
    }
}

package refactoring_guru.builder.example.cars;

public enum CarType {
    CITY_CAR, SPORTS_CAR, SUV
}

package refactoring_guru.builder.example.components;

/**
 * مكوّنٌ آخر من مكوّنات السيارة.
 */
public class Engine {
    private final double volume;
    private double mileage;
    private boolean started;

    public Engine(double volume, double mileage) {
        this.volume = volume;
        this.mileage = mileage;
    }

    public void on() {
        started = true;
    }

    public void off() {
        started = false;
    }

    public boolean isStarted() {
        return started;
    }

    public void go(double mileage) {
        if (started) {
            this.mileage += mileage;
        } else {
            System.err.println("Cannot go(), you must start engine first!");
        }
    }

    public double getVolume() {
        return volume;
    }

    public double getMileage() {
        return mileage;
    }
}

package refactoring_guru.builder.example.components;

/**
 * مكوّنٌ آخر من مكوّنات السيارة.
 */
public class GPSNavigator {
    private String route;

    public GPSNavigator() {
        this.route = "221b, Baker Street, London  to Scotland Yard, 8-10 Broadway, London";
    }

    public GPSNavigator(String manualRoute) {
        this.route = manualRoute;
    }

    public String getRoute() {
        return route;
    }
}

package refactoring_guru.builder.example.components;

/**
 * مكوّنٌ آخر من مكوّنات السيارة.
 */
public enum Transmission {
    SINGLE_SPEED, MANUAL, AUTOMATIC, SEMI_AUTOMATIC
}

package refactoring_guru.builder.example.components;

import refactoring_guru.builder.example.cars.Car;

/**
 * مكوّنٌ آخر من مكوّنات السيارة.
 */
public class TripComputer {

    private Car car;

    public void setCar(Car car) {
        this.car = car;
    }

    public void showFuelLevel() {
        System.out.println("Fuel level: " + car.getFuel());
    }

    public void showStatus() {
        if (this.car.getEngine().isStarted()) {
            System.out.println("Car is started");
        } else {
            System.out.println("Car isn't started");
        }
    }
}

package refactoring_guru.builder.example.director;

import refactoring_guru.builder.example.builders.Builder;
import refactoring_guru.builder.example.cars.CarType;
import refactoring_guru.builder.example.components.Engine;
import refactoring_guru.builder.example.components.GPSNavigator;
import refactoring_guru.builder.example.components.Transmission;
import refactoring_guru.builder.example.components.TripComputer;

/**
 * يُحدّد المُوجّه ترتيب خطوات البناء. يعمل مع كائن البنّاء
 * عبر واجهة Builder المشتركة. لذلك قد لا يعلم أي منتج يُبنى.
 */
public class Director {

    public void constructSportsCar(Builder builder) {
        builder.setCarType(CarType.SPORTS_CAR);
        builder.setSeats(2);
        builder.setEngine(new Engine(3.0, 0));
        builder.setTransmission(Transmission.SEMI_AUTOMATIC);
        builder.setTripComputer(new TripComputer());
        builder.setGPSNavigator(new GPSNavigator());
    }

    public void constructCityCar(Builder builder) {
        builder.setCarType(CarType.CITY_CAR);
        builder.setSeats(2);
        builder.setEngine(new Engine(1.2, 0));
        builder.setTransmission(Transmission.AUTOMATIC);
        builder.setTripComputer(new TripComputer());
        builder.setGPSNavigator(new GPSNavigator());
    }

    public void constructSUV(Builder builder) {
        builder.setCarType(CarType.SUV);
        builder.setSeats(4);
        builder.setEngine(new Engine(2.5, 0));
        builder.setTransmission(Transmission.MANUAL);
        builder.setGPSNavigator(new GPSNavigator());
    }
}

package refactoring_guru.builder.example;

import refactoring_guru.builder.example.builders.CarBuilder;
import refactoring_guru.builder.example.builders.CarManualBuilder;
import refactoring_guru.builder.example.cars.Car;
import refactoring_guru.builder.example.cars.Manual;
import refactoring_guru.builder.example.director.Director;

/**
 * فئة العرض التجريبي. هنا يتلاقى كل شيء.
 */
public class Demo {

    public static void main(String[] args) {
        Director director = new Director();

        // يحصل المُوجّه على كائن البنّاء المحدد من العميل
        // (كود التطبيق). لأن التطبيق يعلم أي بنّاء
        // يجب استخدامه للحصول على منتج معين.
        CarBuilder builder = new CarBuilder();
        director.constructSportsCar(builder);

        // غالبًا ما يُسترد المنتج النهائي من كائن البنّاء، إذ
        // لا يعلم المُوجّه ولا يعتمد على البنّاؤين المحددين
        // والمنتجات.
        Car car = builder.getResult();
        System.out.println("Car built:\n" + car.getCarType());


        CarManualBuilder manualBuilder = new CarManualBuilder();

        // قد يعرف المُوجّه عدة وصفات بناء.
        director.constructSportsCar(manualBuilder);
        Manual carManual = manualBuilder.getResult();
        System.out.println("\nCar manual built:\n" + carManual.print());
    }

}

Car built:
SPORTS_CAR

Car manual built:
Type of car: SPORTS_CAR
Count of seats: 2
Engine: volume - 3.0; mileage - 0.0
Transmission: SEMI_AUTOMATIC
Trip Computer: Functional
GPS Navigator: Functional
```

### csharp

```csharp
using System;
using System.Collections.Generic;

namespace RefactoringGuru.DesignPatterns.Builder.Conceptual
{
    // تُحدّد واجهة Builder التوابع الخاصة بإنشاء الأجزاء المختلفة
    // من كائنات المنتج.
    public interface IBuilder
    {
        void BuildPartA();
		
        void BuildPartB();
		
        void BuildPartC();
    }
    
    // تتبع فئات البنّاء المحدد واجهة Builder وتوفر
    // تطبيقات محددة لخطوات البناء. قد يكون لديك
    // عدة تنوعات من البنّاؤين مُطبَّقة بشكل مختلف.
    public class ConcreteBuilder : IBuilder
    {
        private Product _product = new Product();
        
        // يجب أن يحتوي نموذج البنّاء الجديد على كائن منتج فارغ
        // يُستخدم في عملية التجميع اللاحقة.
        public ConcreteBuilder()
        {
            this.Reset();
        }
        
        public void Reset()
        {
            this._product = new Product();
        }
		
        // جميع خطوات الإنتاج تعمل مع نفس نموذج المنتج.
        public void BuildPartA()
        {
            this._product.Add("PartA1");
        }
		
        public void BuildPartB()
        {
            this._product.Add("PartB1");
        }
		
        public void BuildPartC()
        {
            this._product.Add("PartC1");
        }
		
        // من المفترض أن يوفر البنّاؤون المحددون توابعهم الخاصة
        // لاسترداد النتائج. لأن أنواعًا مختلفة من البنّاؤين قد تُنشئ
        // منتجات مختلفة تمامًا لا تتبع نفس الواجهة.
        // لذلك لا يمكن الإعلان عن هذه التوابع في واجهة
        // Builder الأساسية (على الأقل في لغات البرمجة ذات
        // الأنواع الستاتيكية).
        //
        // عادةً، بعد إعادة النتيجة النهائية إلى العميل، يُتوقع
        // من نموذج البنّاء أن يكون جاهزًا لبدء إنتاج منتج آخر.
        // لهذا السبب من الشائع استدعاء تابع reset في نهاية
        // جسم تابع `GetProduct`. ومع ذلك، هذا السلوك
        // ليس إلزاميًا، ويمكنك جعل البنّاؤين ينتظرون
        // استدعاء reset صريحًا من كود العميل قبل التخلص من النتيجة السابقة.
        public Product GetProduct()
        {
            Product result = this._product;

            this.Reset();

            return result;
        }
    }
    
    // استخدام نمط Builder منطقي فقط عندما تكون منتجاتك
    // معقدةً جدًا وتتطلب تهيئةً مكثفة.
    //
    // على خلاف أنماط الإنشاء الأخرى، يمكن للبنّاؤين المحددين المختلفين
    // إنتاج منتجات غير مرتبطة. بمعنى آخر، نتائج البنّاؤين المختلفين
    // قد لا تتبع دائمًا نفس الواجهة.
    public class Product
    {
        private List<object> _parts = new List<object>();
		
        public void Add(string part)
        {
            this._parts.Add(part);
        }
		
        public string ListParts()
        {
            string str = string.Empty;

            for (int i = 0; i < this._parts.Count; i++)
            {
                str += this._parts[i] + ", ";
            }

            str = str.Remove(str.Length - 2); // حذف آخر ","

            return "Product parts: " + str + "\n";
        }
    }
    
    // المُوجّه مسؤول فقط عن تنفيذ خطوات البناء
    // بتسلسل معين. يفيد ذلك عند إنتاج منتجات وفق
    // ترتيب أو تهيئة محددة. بالمعنى الدقيق، فئة المُوجّه
    // اختيارية، إذ يمكن للعميل التحكم في البنّاؤين مباشرةً.
    public class Director
    {
        private IBuilder _builder;
        
        public IBuilder Builder
        {
            set { _builder = value; } 
        }
        
        // يمكن للمُوجّه بناء عدة تنوعات من المنتج
        // باستخدام نفس خطوات البناء.
        public void BuildMinimalViableProduct()
        {
            this._builder.BuildPartA();
        }
		
        public void BuildFullFeaturedProduct()
        {
            this._builder.BuildPartA();
            this._builder.BuildPartB();
            this._builder.BuildPartC();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            // يُنشئ كود العميل كائن البنّاء ويُمرّره إلى المُوجّه
            // ثم يُطلق عملية البناء. يُسترد
            // الناتج النهائي من كائن البنّاء.
            var director = new Director();
            var builder = new ConcreteBuilder();
            director.Builder = builder;
            
            Console.WriteLine("Standard basic product:");
            director.BuildMinimalViableProduct();
            Console.WriteLine(builder.GetProduct().ListParts());

            Console.WriteLine("Standard full featured product:");
            director.BuildFullFeaturedProduct();
            Console.WriteLine(builder.GetProduct().ListParts());

            // تذكّر، يمكن استخدام نمط Builder دون فئة مُوجّه.
            Console.WriteLine("Custom product:");
            builder.BuildPartA();
            builder.BuildPartC();
            Console.Write(builder.GetProduct().ListParts());
        }
    }
}

Standard basic product:
Product parts: PartA1

Standard full featured product:
Product parts: PartA1, PartB1, PartC1

Custom product:
Product parts: PartA1, PartC1
```

### cpp

```cpp
/**
 * استخدام نمط Builder منطقي فقط عندما تكون منتجاتك معقدةً جدًا
 * وتتطلب تهيئةً مكثفة.
 *
 * على خلاف أنماط الإنشاء الأخرى، يمكن للبنّاؤين المحددين المختلفين إنتاج
 * منتجات غير مرتبطة. بمعنى آخر، نتائج البنّاؤين المختلفين قد لا تتبع
 * دائمًا نفس الواجهة.
 */

class Product1{
    public:
    std::vector<std::string> parts_;
    void ListParts()const{
        std::cout << "Product parts: ";
        for (size_t i=0;i<parts_.size();i++){
            if(parts_[i]== parts_.back()){
                std::cout << parts_[i];
            }else{
                std::cout << parts_[i] << ", ";
            }
        }
        std::cout << "\n\n"; 
    }
};


/**
 * تُحدّد واجهة Builder التوابع الخاصة بإنشاء الأجزاء المختلفة
 * من كائنات المنتج.
 */
class Builder{
    public:
    virtual ~Builder(){}
    virtual void ProducePartA() const =0;
    virtual void ProducePartB() const =0;
    virtual void ProducePartC() const =0;
};
/**
 * تتبع فئات البنّاء المحدد واجهة Builder وتوفر تطبيقات محددة
 * لخطوات البناء. قد يكون لديك عدة تنوعات من البنّاؤين
 * مُطبَّقة بشكل مختلف في برنامجك.
 */
class ConcreteBuilder1 : public Builder{
    private:

    Product1* product;

    /**
     * يجب أن يحتوي نموذج البنّاء الجديد على كائن منتج فارغ يُستخدم
     * في عملية التجميع اللاحقة.
     */
    public:

    ConcreteBuilder1(){
        this->Reset();
    }

    ~ConcreteBuilder1(){
        delete product;
    }

    void Reset(){
        this->product= new Product1();
    }
    /**
     * جميع خطوات الإنتاج تعمل مع نفس نموذج المنتج.
     */

    void ProducePartA()const override{
        this->product->parts_.push_back("PartA1");
    }

    void ProducePartB()const override{
        this->product->parts_.push_back("PartB1");
    }

    void ProducePartC()const override{
        this->product->parts_.push_back("PartC1");
    }

    /**
     * من المفترض أن يوفر البنّاؤون المحددون توابعهم الخاصة لاسترداد النتائج.
     * لأن أنواعًا مختلفة من البنّاؤين قد تُنشئ منتجات مختلفة تمامًا
     * لا تتبع نفس الواجهة. لذلك لا يمكن الإعلان عن هذه التوابع
     * في واجهة Builder الأساسية (على الأقل في لغات البرمجة ذات الأنواع الستاتيكية).
     * لاحظ أن PHP لغة ذات أنواع ديناميكية وهذا التابع يمكن وجوده في الواجهة الأساسية.
     * ومع ذلك لن نُعلن عنه هناك من أجل الوضوح.
     *
     * عادةً، بعد إعادة النتيجة النهائية إلى العميل، يُتوقع من نموذج البنّاء
     * أن يكون جاهزًا لبدء إنتاج منتج آخر. لهذا السبب من الشائع
     * استدعاء تابع reset في نهاية جسم تابع `getProduct`.
     * ومع ذلك، هذا السلوك ليس إلزاميًا، ويمكنك جعل البنّاؤين ينتظرون
     * استدعاء reset صريحًا من كود العميل قبل التخلص من النتيجة السابقة.
     */

    /**
     * انتبه هنا لملكية الذاكرة. بمجرد استدعاء GetProduct يصبح
     * مستخدم هذه الدالة مسؤولًا عن تحرير هذه الذاكرة.
     * يُعدّ استخدام المؤشرات الذكية خيارًا أفضل لتجنب تسرب الذاكرة.
     */

    Product1* GetProduct() {
        Product1* result= this->product;
        this->Reset();
        return result;
    }
};

/**
 * المُوجّه مسؤول فقط عن تنفيذ خطوات البناء بتسلسل معين.
 * يفيد ذلك عند إنتاج منتجات وفق ترتيب أو تهيئة محددة.
 * بالمعنى الدقيق، فئة المُوجّه اختيارية إذ يمكن للعميل
 * التحكم في البنّاؤين مباشرةً.
 */
class Director{
    /**
     * @var Builder
     */
    private:
    Builder* builder;
    /**
     * يعمل المُوجّه مع أي نموذج بنّاء يُمرّره إليه كود العميل.
     * بهذه الطريقة يمكن لكود العميل تغيير النوع النهائي للمنتج المُجمَّع حديثًا.
     */

    public:

    void set_builder(Builder* builder){
        this->builder=builder;
    }

    /**
     * يمكن للمُوجّه بناء عدة تنوعات من المنتج باستخدام نفس خطوات البناء.
     */

    void BuildMinimalViableProduct(){
        this->builder->ProducePartA();
    }
    
    void BuildFullFeaturedProduct(){
        this->builder->ProducePartA();
        this->builder->ProducePartB();
        this->builder->ProducePartC();
    }
};
/**
 * يُنشئ كود العميل كائن البنّاء ويُمرّره إلى المُوجّه ثم يُطلق
 * عملية البناء. يُسترد الناتج النهائي من كائن البنّاء.
 */
/**
 * استخدمت المؤشرات الخام هنا للبساطة لكن يُفضَّل استخدام المؤشرات الذكية.
 */
void ClientCode(Director& director)
{
    ConcreteBuilder1* builder = new ConcreteBuilder1();
    director.set_builder(builder);
    std::cout << "Standard basic product:\n"; 
    director.BuildMinimalViableProduct();
    
    Product1* p= builder->GetProduct();
    p->ListParts();
    delete p;

    std::cout << "Standard full featured product:\n"; 
    director.BuildFullFeaturedProduct();

    p= builder->GetProduct();
    p->ListParts();
    delete p;

    // تذكّر، يمكن استخدام نمط Builder دون فئة مُوجّه.
    std::cout << "Custom product:\n";
    builder->ProducePartA();
    builder->ProducePartC();
    p=builder->GetProduct();
    p->ListParts();
    delete p;

    delete builder;
}

int main(){
    Director* director= new Director();
    ClientCode(*director);
    delete director;
    return 0;    
}

Standard basic product:
Product parts: PartA1

Standard full featured product:
Product parts: PartA1, PartB1, PartC1

Custom product:
Product parts: PartA1, PartC1
```

### go

```go
package main

type IBuilder interface {
	setWindowType()
	setDoorType()
	setNumFloor()
	getHouse() House
}

func getBuilder(builderType string) IBuilder {
	if builderType == "normal" {
		return newNormalBuilder()
	}

	if builderType == "igloo" {
		return newIglooBuilder()
	}
	return nil
}

package main

type NormalBuilder struct {
	windowType string
	doorType   string
	floor      int
}

func newNormalBuilder() *NormalBuilder {
	return &NormalBuilder{}
}

func (b *NormalBuilder) setWindowType() {
	b.windowType = "Wooden Window"
}

func (b *NormalBuilder) setDoorType() {
	b.doorType = "Wooden Door"
}

func (b *NormalBuilder) setNumFloor() {
	b.floor = 2
}

func (b *NormalBuilder) getHouse() House {
	return House{
		doorType:   b.doorType,
		windowType: b.windowType,
		floor:      b.floor,
	}
}

package main

type IglooBuilder struct {
	windowType string
	doorType   string
	floor      int
}

func newIglooBuilder() *IglooBuilder {
	return &IglooBuilder{}
}

func (b *IglooBuilder) setWindowType() {
	b.windowType = "Snow Window"
}

func (b *IglooBuilder) setDoorType() {
	b.doorType = "Snow Door"
}

func (b *IglooBuilder) setNumFloor() {
	b.floor = 1
}

func (b *IglooBuilder) getHouse() House {
	return House{
		doorType:   b.doorType,
		windowType: b.windowType,
		floor:      b.floor,
	}
}

package main

type House struct {
	windowType string
	doorType   string
	floor      int
}

package main

type Director struct {
	builder IBuilder
}

func newDirector(b IBuilder) *Director {
	return &Director{
		builder: b,
	}
}

func (d *Director) setBuilder(b IBuilder) {
	d.builder = b
}

func (d *Director) buildHouse() House {
	d.builder.setDoorType()
	d.builder.setWindowType()
	d.builder.setNumFloor()
	return d.builder.getHouse()
}

package main

import "fmt"

func main() {
	normalBuilder := getBuilder("normal")
	iglooBuilder := getBuilder("igloo")

	director := newDirector(normalBuilder)
	normalHouse := director.buildHouse()

	fmt.Printf("Normal House Door Type: %s\n", normalHouse.doorType)
	fmt.Printf("Normal House Window Type: %s\n", normalHouse.windowType)
	fmt.Printf("Normal House Num Floor: %d\n", normalHouse.floor)

	director.setBuilder(iglooBuilder)
	iglooHouse := director.buildHouse()

	fmt.Printf("\nIgloo House Door Type: %s\n", iglooHouse.doorType)
	fmt.Printf("Igloo House Window Type: %s\n", iglooHouse.windowType)
	fmt.Printf("Igloo House Num Floor: %d\n", iglooHouse.floor)

}

Normal House Door Type: Wooden Door
Normal House Window Type: Wooden Window
Normal House Num Floor: 2

Igloo House Door Type: Snow Door
Igloo House Window Type: Snow Window
Igloo House Num Floor: 1
```

### php

```php
<?php

namespace RefactoringGuru\Builder\Conceptual;

/**
 * تُحدّد واجهة Builder التوابع الخاصة بإنشاء الأجزاء المختلفة
 * من كائنات المنتج.
 */
interface Builder
{
    public function producePartA(): void;

    public function producePartB(): void;

    public function producePartC(): void;
}

/**
 * تتبع فئات البنّاء المحدد واجهة Builder وتوفر تطبيقات محددة
 * لخطوات البناء. قد يكون لديك عدة تنوعات من البنّاؤين
 * مُطبَّقة بشكل مختلف في برنامجك.
 */
class ConcreteBuilder1 implements Builder
{
    private $product;

    /**
     * يجب أن يحتوي نموذج البنّاء الجديد على كائن منتج فارغ يُستخدم
     * في عملية التجميع اللاحقة.
     */
    public function __construct()
    {
        $this->reset();
    }

    public function reset(): void
    {
        $this->product = new Product1();
    }

    /**
     * جميع خطوات الإنتاج تعمل مع نفس نموذج المنتج.
     */
    public function producePartA(): void
    {
        $this->product->parts[] = "PartA1";
    }

    public function producePartB(): void
    {
        $this->product->parts[] = "PartB1";
    }

    public function producePartC(): void
    {
        $this->product->parts[] = "PartC1";
    }

    /**
     * من المفترض أن يوفر البنّاؤون المحددون توابعهم الخاصة لاسترداد النتائج.
     * لأن أنواعًا مختلفة من البنّاؤين قد تُنشئ منتجات مختلفة تمامًا
     * لا تتبع نفس الواجهة. لذلك لا يمكن الإعلان عن هذه التوابع
     * في واجهة Builder الأساسية (على الأقل في لغات البرمجة ذات الأنواع الستاتيكية).
     * لاحظ أن PHP لغة ذات أنواع ديناميكية وهذا التابع يمكن وجوده في الواجهة الأساسية.
     * ومع ذلك لن نُعلن عنه هناك من أجل الوضوح.
     *
     * عادةً، بعد إعادة النتيجة النهائية إلى العميل، يُتوقع من نموذج البنّاء
     * أن يكون جاهزًا لبدء إنتاج منتج آخر. لهذا السبب من الشائع
     * استدعاء تابع reset في نهاية جسم تابع `getProduct`.
     * ومع ذلك، هذا السلوك ليس إلزاميًا، ويمكنك جعل البنّاؤين ينتظرون
     * استدعاء reset صريحًا من كود العميل قبل التخلص من النتيجة السابقة.
     */
    public function getProduct(): Product1
    {
        $result = $this->product;
        $this->reset();

        return $result;
    }
}

/**
 * استخدام نمط Builder منطقي فقط عندما تكون منتجاتك معقدةً جدًا
 * وتتطلب تهيئةً مكثفة.
 *
 * على خلاف أنماط الإنشاء الأخرى، يمكن للبنّاؤين المحددين المختلفين إنتاج
 * منتجات غير مرتبطة. بمعنى آخر، نتائج البنّاؤين المختلفين قد لا تتبع
 * دائمًا نفس الواجهة.
 */
class Product1
{
    public $parts = [];

    public function listParts(): void
    {
        echo "Product parts: " . implode(', ', $this->parts) . "\n\n";
    }
}

/**
 * المُوجّه مسؤول فقط عن تنفيذ خطوات البناء بتسلسل معين.
 * يفيد ذلك عند إنتاج منتجات وفق ترتيب أو تهيئة محددة.
 * بالمعنى الدقيق، فئة المُوجّه اختيارية إذ يمكن للعميل
 * التحكم في البنّاؤين مباشرةً.
 */
class Director
{
    /**
     * @var Builder
     */
    private $builder;

    /**
     * يعمل المُوجّه مع أي نموذج بنّاء يُمرّره إليه كود العميل.
     * بهذه الطريقة يمكن لكود العميل تغيير النوع النهائي للمنتج المُجمَّع حديثًا.
     */
    public function setBuilder(Builder $builder): void
    {
        $this->builder = $builder;
    }

    /**
     * يمكن للمُوجّه بناء عدة تنوعات من المنتج باستخدام نفس خطوات البناء.
     */
    public function buildMinimalViableProduct(): void
    {
        $this->builder->producePartA();
    }

    public function buildFullFeaturedProduct(): void
    {
        $this->builder->producePartA();
        $this->builder->producePartB();
        $this->builder->producePartC();
    }
}

/**
 * يُنشئ كود العميل كائن البنّاء ويُمرّره إلى المُوجّه ثم يُطلق
 * عملية البناء. يُسترد الناتج النهائي من كائن البنّاء.
 */
function clientCode(Director $director)
{
    $builder = new ConcreteBuilder1();
    $director->setBuilder($builder);

    echo "Standard basic product:\n";
    $director->buildMinimalViableProduct();
    $builder->getProduct()->listParts();

    echo "Standard full featured product:\n";
    $director->buildFullFeaturedProduct();
    $builder->getProduct()->listParts();

    // تذكّر، يمكن استخدام نمط Builder دون فئة مُوجّه.
    echo "Custom product:\n";
    $builder->producePartA();
    $builder->producePartC();
    $builder->getProduct()->listParts();
}

$director = new Director();
clientCode($director);

Standard basic product:
Product parts: PartA1

Standard full featured product:
Product parts: PartA1, PartB1, PartC1

Custom product:
Product parts: PartA1, PartC1

<?php

namespace RefactoringGuru\Builder\RealWorld;

/**
 * The Builder interface declares a set of methods to assemble an SQL query.
 *
 * All of the construction steps are returning the current builder object to
 * allow chaining: $builder->select(...)->where(...)
 */
interface SQLQueryBuilder
{
    public function select(string $table, array $fields): SQLQueryBuilder;

    public function where(string $field, string $value, string $operator = '='): SQLQueryBuilder;

    public function limit(int $start, int $offset): SQLQueryBuilder;

    // +100 تابع آخر لصياغة SQL...

    public function getSQL(): string;
}

/**
 * يتوافق كل بنّاء محدد مع لهجة SQL معينة وقد يُطبّق
 * خطوات البنّاء بشكل مختلف قليلًا عن الآخرين.
 *
 * يمكن لهذا البنّاء المحدد بناء استعلامات SQL متوافقة مع MySQL.
 */
class MysqlQueryBuilder implements SQLQueryBuilder
{
    protected $query;

    protected function reset(): void
    {
        $this->query = new \stdClass();
    }

    /**
     * بناء استعلام SELECT أساسي.
     */
    public function select(string $table, array $fields): SQLQueryBuilder
    {
        $this->reset();
        $this->query->base = "SELECT " . implode(", ", $fields) . " FROM " . $table;
        $this->query->type = 'select';

        return $this;
    }

    /**
     * إضافة شرط WHERE.
     */
    public function where(string $field, string $value, string $operator = '='): SQLQueryBuilder
    {
        if (!in_array($this->query->type, ['select', 'update', 'delete'])) {
            throw new \Exception("WHERE can only be added to SELECT, UPDATE OR DELETE");
        }
        $this->query->where[] = "$field $operator '$value'";

        return $this;
    }

    /**
     * إضافة قيد LIMIT.
     */
    public function limit(int $start, int $offset): SQLQueryBuilder
    {
        if (!in_array($this->query->type, ['select'])) {
            throw new \Exception("LIMIT can only be added to SELECT");
        }
        $this->query->limit = " LIMIT " . $start . ", " . $offset;

        return $this;
    }

    /**
     * الحصول على نص الاستعلام النهائي.
     */
    public function getSQL(): string
    {
        $query = $this->query;
        $sql = $query->base;
        if (!empty($query->where)) {
            $sql .= " WHERE " . implode(' AND ', $query->where);
        }
        if (isset($query->limit)) {
            $sql .= $query->limit;
        }
        $sql .= ";";
        return $sql;
    }
}

/**
 * هذا البنّاء المحدد متوافق مع PostgreSQL. بينما يتشابه Postgres كثيرًا
 * مع MySQL، لا يزال هناك عدة اختلافات. لإعادة استخدام الكود المشترك،
 * نرث من بنّاء MySQL مع تجاوز بعض خطوات البناء.
 */
class PostgresQueryBuilder extends MysqlQueryBuilder
{
    /**
     * من بين أمور أخرى، يمتلك PostgreSQL صياغة LIMIT مختلفة قليلًا.
     */
    public function limit(int $start, int $offset): SQLQueryBuilder
    {
        parent::limit($start, $offset);

        $this->query->limit = " LIMIT " . $start . " OFFSET " . $offset;

        return $this;
    }

    // + الكثير من التجاوزات الأخرى...
}


/**
 * لاحظ أن كود العميل يستخدم كائن البنّاء مباشرةً. لا تُعدّ فئة المُوجّه
 * ضرورية في هذه الحالة، لأن كود العميل يحتاج إلى استعلامات مختلفة
 * في كل مرة تقريبًا، لذا لا يمكن إعادة استخدام تسلسل
 * خطوات البناء بسهولة.
 *
 * نظرًا لأن جميع بنّاؤي الاستعلامات لدينا تُنشئ منتجات من نفس النوع
 * (وهو سلسلة نصية)، يمكننا التفاعل مع جميع البنّاؤين عبر واجهتهم المشتركة.
 * لاحقًا، إذا طبّقنا فئة Builder جديدة، سنتمكن من تمرير نموذجها
 * إلى كود العميل الموجود دون كسره بفضل واجهة SQLQueryBuilder.
 */
function clientCode(SQLQueryBuilder $queryBuilder)
{
    // ...

    $query = $queryBuilder
        ->select("users", ["name", "email", "password"])
        ->where("age", 18, ">")
        ->where("age", 30, "<")
        ->limit(10, 20)
        ->getSQL();

    echo $query;

    // ...
}


/**
 * The application selects the proper query builder type depending on a current
 * configuration or the environment settings.
 */
// if ($_ENV['database_type'] == 'postgres') {
//     $builder = new PostgresQueryBuilder(); } else {
//     $builder = new MysqlQueryBuilder(); }
//
// clientCode($builder);


echo "Testing MySQL query builder:\n";
clientCode(new MysqlQueryBuilder());

echo "\n\n";

echo "Testing PostgresSQL query builder:\n";
clientCode(new PostgresQueryBuilder());

Testing MySQL query builder:
SELECT name, email, password FROM users WHERE age > '18' AND age < '30' LIMIT 10, 20;

Testing PostgresSQL query builder:
SELECT name, email, password FROM users WHERE age > '18' AND age < '30' LIMIT 10 OFFSET 20;
```

### python

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


class Builder(ABC):
    """
    تُحدّد واجهة Builder التوابع الخاصة بإنشاء الأجزاء المختلفة
    من كائنات المنتج.
    """

    @property
    @abstractmethod
    def product(self) -> None:
        pass

    @abstractmethod
    def produce_part_a(self) -> None:
        pass

    @abstractmethod
    def produce_part_b(self) -> None:
        pass

    @abstractmethod
    def produce_part_c(self) -> None:
        pass


class ConcreteBuilder1(Builder):
    """
    تتبع فئات البنّاء المحدد واجهة Builder وتوفر تطبيقات محددة
    لخطوات البناء. قد يكون لديك عدة تنوعات من البنّاؤين
    مُطبَّقة بشكل مختلف في برنامجك.
    """

    def __init__(self) -> None:
        """
        يجب أن يحتوي نموذج البنّاء الجديد على كائن منتج فارغ يُستخدم
        في عملية التجميع اللاحقة.
        """
        self.reset()

    def reset(self) -> None:
        self._product = Product1()

    @property
    def product(self) -> Product1:
        """
        من المفترض أن يوفر البنّاؤون المحددون توابعهم الخاصة لاسترداد النتائج.
        لأن أنواعًا مختلفة من البنّاؤين قد تُنشئ منتجات مختلفة تمامًا
        لا تتبع نفس الواجهة. لذلك لا يمكن الإعلان عن هذه التوابع
        في واجهة Builder الأساسية (على الأقل في لغات البرمجة ذات الأنواع الستاتيكية).

        عادةً، بعد إعادة النتيجة النهائية إلى العميل، يُتوقع من نموذج البنّاء
        أن يكون جاهزًا لبدء إنتاج منتج آخر. لهذا السبب من الشائع
        استدعاء تابع reset في نهاية جسم تابع `getProduct`.
        ومع ذلك، هذا السلوك ليس إلزاميًا، ويمكنك جعل البنّاؤين ينتظرون
        استدعاء reset صريحًا من كود العميل قبل التخلص من النتيجة السابقة.
        """
        product = self._product
        self.reset()
        return product

    def produce_part_a(self) -> None:
        self._product.add("PartA1")

    def produce_part_b(self) -> None:
        self._product.add("PartB1")

    def produce_part_c(self) -> None:
        self._product.add("PartC1")


class Product1():
    """
    استخدام نمط Builder منطقي فقط عندما تكون منتجاتك معقدةً جدًا
    وتتطلب تهيئةً مكثفة.

    على خلاف أنماط الإنشاء الأخرى، يمكن للبنّاؤين المحددين المختلفين إنتاج
    منتجات غير مرتبطة. بمعنى آخر، نتائج البنّاؤين المختلفين قد لا تتبع
    دائمًا نفس الواجهة.
    """

    def __init__(self) -> None:
        self.parts = []

    def add(self, part: Any) -> None:
        self.parts.append(part)

    def list_parts(self) -> None:
        print(f"Product parts: {', '.join(self.parts)}", end="")


class Director:
    """
    المُوجّه مسؤول فقط عن تنفيذ خطوات البناء بتسلسل معين.
    يفيد ذلك عند إنتاج منتجات وفق ترتيب أو تهيئة محددة.
    بالمعنى الدقيق، فئة المُوجّه اختيارية إذ يمكن للعميل
    التحكم في البنّاؤين مباشرةً.
    """

    def __init__(self) -> None:
        self._builder = None

    @property
    def builder(self) -> Builder:
        return self._builder

    @builder.setter
    def builder(self, builder: Builder) -> None:
        """
        يعمل المُوجّه مع أي نموذج بنّاء يُمرّره إليه كود العميل.
        بهذه الطريقة يمكن لكود العميل تغيير النوع النهائي للمنتج المُجمَّع حديثًا.
        """
        self._builder = builder

    """
    يمكن للمُوجّه بناء عدة تنوعات من المنتج باستخدام نفس خطوات البناء.
    """

    def build_minimal_viable_product(self) -> None:
        self.builder.produce_part_a()

    def build_full_featured_product(self) -> None:
        self.builder.produce_part_a()
        self.builder.produce_part_b()
        self.builder.produce_part_c()


if __name__ == "__main__":
    """
    يُنشئ كود العميل كائن البنّاء ويُمرّره إلى المُوجّه ثم يُطلق
    عملية البناء. يُسترد الناتج النهائي من كائن البنّاء.
    """

    director = Director()
    builder = ConcreteBuilder1()
    director.builder = builder

    print("Standard basic product: ")
    director.build_minimal_viable_product()
    builder.product.list_parts()

    print("\n")

    print("Standard full featured product: ")
    director.build_full_featured_product()
    builder.product.list_parts()

    print("\n")

    # تذكّر، يمكن استخدام نمط Builder دون فئة مُوجّه.
    print("Custom product: ")
    builder.produce_part_a()
    builder.produce_part_b()
    builder.product.list_parts()

Standard basic product: 
Product parts: PartA1

Standard full featured product: 
Product parts: PartA1, PartB1, PartC1

Custom product: 
Product parts: PartA1, PartB1
```

### ruby

```ruby
# تُحدّد واجهة Builder التوابع الخاصة بإنشاء الأجزاء المختلفة
# من كائنات المنتج.
class Builder
  # @abstract
  def produce_part_a
    raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
  end

  # @abstract
  def produce_part_b
    raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
  end

  # @abstract
  def produce_part_c
    raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
  end
end

# تتبع فئات البنّاء المحدد واجهة Builder وتوفر تطبيقات محددة
# لخطوات البناء. قد يكون لديك عدة تنوعات من البنّاؤين
# مُطبَّقة بشكل مختلف في برنامجك.
class ConcreteBuilder1 < Builder
  # يجب أن يحتوي نموذج البنّاء الجديد على كائن منتج فارغ يُستخدم
  # في عملية التجميع اللاحقة.
  def initialize
    reset
  end

  def reset
    @product = Product1.new
  end

  # من المفترض أن يوفر البنّاؤون المحددون توابعهم الخاصة لاسترداد النتائج.
  # لأن أنواعًا مختلفة من البنّاؤين قد تُنشئ منتجات مختلفة تمامًا
  # لا تتبع نفس الواجهة. لذلك لا يمكن الإعلان عن هذه التوابع
  # في واجهة Builder الأساسية (على الأقل في لغات البرمجة ذات الأنواع الستاتيكية).
  #
  # عادةً، بعد إعادة النتيجة النهائية إلى العميل، يُتوقع من نموذج البنّاء
  # أن يكون جاهزًا لبدء إنتاج منتج آخر. لهذا السبب من الشائع
  # استدعاء تابع reset في نهاية جسم تابع `getProduct`.
  # ومع ذلك، هذا السلوك ليس إلزاميًا، ويمكنك جعل البنّاؤين ينتظرون
  # استدعاء reset صريحًا من كود العميل قبل التخلص من النتيجة السابقة.
  def product
    product = @product
    reset
    product
  end

  def produce_part_a
    @product.add('PartA1')
  end

  def produce_part_b
    @product.add('PartB1')
  end

  def produce_part_c
    @product.add('PartC1')
  end
end

# استخدام نمط Builder منطقي فقط عندما تكون منتجاتك معقدةً جدًا
# وتتطلب تهيئةً مكثفة.
#
# على خلاف أنماط الإنشاء الأخرى، يمكن للبنّاؤين المحددين المختلفين إنتاج
# منتجات غير مرتبطة. بمعنى آخر، نتائج البنّاؤين المختلفين قد لا تتبع
# دائمًا نفس الواجهة.
class Product1
  def initialize
    @parts = []
  end

  # @param [String] part
  def add(part)
    @parts << part
  end

  def list_parts
    print "Product parts: #{@parts.join(', ')}"
  end
end

# المُوجّه مسؤول فقط عن تنفيذ خطوات البناء بتسلسل معين.
# يفيد ذلك عند إنتاج منتجات وفق ترتيب أو تهيئة محددة.
# بالمعنى الدقيق، فئة المُوجّه اختيارية إذ يمكن للعميل
# التحكم في البنّاؤين مباشرةً.
class Director
  # @return [Builder]
  attr_accessor :builder

  def initialize
    @builder = nil
  end

  # يعمل المُوجّه مع أي نموذج بنّاء يُمرّره إليه كود العميل.
  # بهذه الطريقة يمكن لكود العميل تغيير النوع النهائي للمنتج المُجمَّع حديثًا.
  def builder=(builder)
    @builder = builder
  end

  # يمكن للمُوجّه بناء عدة تنوعات من المنتج باستخدام نفس خطوات البناء.

  def build_minimal_viable_product
    @builder.produce_part_a
  end

  def build_full_featured_product
    @builder.produce_part_a
    @builder.produce_part_b
    @builder.produce_part_c
  end
end

# يُنشئ كود العميل كائن البنّاء ويُمرّره إلى المُوجّه ثم يُطلق
# عملية البناء. يُسترد الناتج النهائي من كائن البنّاء.

director = Director.new
builder = ConcreteBuilder1.new
director.builder = builder

puts 'Standard basic product: '
director.build_minimal_viable_product
builder.product.list_parts

puts "\n\n"

puts 'Standard full featured product: '
director.build_full_featured_product
builder.product.list_parts

puts "\n\n"

# تذكّر، يمكن استخدام نمط Builder دون فئة مُوجّه.
puts 'Custom product: '
builder.produce_part_a
builder.produce_part_b
builder.product.list_parts

Standard basic product: 
Product parts: PartA1

Standard full featured product: 
Product parts: PartA1, PartB1, PartC1

Custom product: 
Product parts: PartA1, PartB1
```

### rust

```rust
let car = Car::default().places(5).gas(30)

mod car;
mod car_manual;

use crate::components::{CarType, Engine, GpsNavigator, Transmission};

/// يُعرّف البنّاء كيفية تجميع سيارة.
pub trait Builder {
    type OutputType;
    fn set_car_type(&mut self, car_type: CarType);
    fn set_seats(&mut self, seats: u16);
    fn set_engine(&mut self, engine: Engine);
    fn set_transmission(&mut self, transmission: Transmission);
    fn set_gps_navigator(&mut self, gps_navigator: GpsNavigator);
    fn build(self) -> Self::OutputType;
}

pub use car::CarBuilder;
pub use car_manual::CarManualBuilder;

use crate::{
    cars::Car,
    components::{CarType, Engine, GpsNavigator, Transmission},
};

use super::Builder;

pub const DEFAULT_FUEL: f64 = 5f64;

#[derive(Default)]
pub struct CarBuilder {
    car_type: Option<CarType>,
    engine: Option<Engine>,
    gps_navigator: Option<GpsNavigator>,
    seats: Option<u16>,
    transmission: Option<Transmission>,
}

impl Builder for CarBuilder {
    type OutputType = Car;

    fn set_car_type(&mut self, car_type: CarType) {
        self.car_type = Some(car_type);
    }

    fn set_engine(&mut self, engine: Engine) {
        self.engine = Some(engine);
    }

    fn set_gps_navigator(&mut self, gps_navigator: GpsNavigator) {
        self.gps_navigator = Some(gps_navigator);
    }

    fn set_seats(&mut self, seats: u16) {
        self.seats = Some(seats);
    }

    fn set_transmission(&mut self, transmission: Transmission) {
        self.transmission = Some(transmission);
    }

    fn build(self) -> Car {
        Car::new(
            self.car_type.expect("Please, set a car type"),
            self.seats.expect("Please, set a number of seats"),
            self.engine.expect("Please, set an engine configuration"),
            self.transmission.expect("Please, set up transmission"),
            self.gps_navigator,
            DEFAULT_FUEL,
        )
    }
}

use crate::{
    cars::Manual,
    components::{CarType, Engine, GpsNavigator, Transmission},
};

use super::Builder;

#[derive(Default)]
pub struct CarManualBuilder {
    car_type: Option<CarType>,
    engine: Option<Engine>,
    gps_navigator: Option<GpsNavigator>,
    seats: Option<u16>,
    transmission: Option<Transmission>,
}

/// يبني دليل سيارة بدلًا من سيارة فعلية.
impl Builder for CarManualBuilder {
    type OutputType = Manual;

    fn set_car_type(&mut self, car_type: CarType) {
        self.car_type = Some(car_type);
    }

    fn set_engine(&mut self, engine: Engine) {
        self.engine = Some(engine);
    }

    fn set_gps_navigator(&mut self, gps_navigator: GpsNavigator) {
        self.gps_navigator = Some(gps_navigator);
    }

    fn set_seats(&mut self, seats: u16) {
        self.seats = Some(seats);
    }

    fn set_transmission(&mut self, transmission: Transmission) {
        self.transmission = Some(transmission);
    }

    fn build(self) -> Manual {
        Manual::new(
            self.car_type.expect("Please, set a car type"),
            self.seats.expect("Please, set a number of seats"),
            self.engine.expect("Please, set an engine configuration"),
            self.transmission.expect("Please, set up transmission"),
            self.gps_navigator,
        )
    }
}

mod car;
mod manual;

pub use car::Car;
pub use manual::Manual;

use crate::components::{CarType, Engine, GpsNavigator, Transmission};

pub struct Car {
    car_type: CarType,
    seats: u16,
    engine: Engine,
    transmission: Transmission,
    gps_navigator: Option<GpsNavigator>,
    fuel: f64,
}

impl Car {
    pub fn new(
        car_type: CarType,
        seats: u16,
        engine: Engine,
        transmission: Transmission,
        gps_navigator: Option<GpsNavigator>,
        fuel: f64,
    ) -> Self {
        Self {
            car_type,
            seats,
            engine,
            transmission,
            gps_navigator,
            fuel,
        }
    }

    pub fn car_type(&self) -> CarType {
        self.car_type
    }

    pub fn fuel(&self) -> f64 {
        self.fuel
    }

    pub fn set_fuel(&mut self, fuel: f64) {
        self.fuel = fuel;
    }

    pub fn seats(&self) -> u16 {
        self.seats
    }

    pub fn engine(&self) -> &Engine {
        &self.engine
    }

    pub fn transmission(&self) -> &Transmission {
        &self.transmission
    }

    pub fn gps_navigator(&self) -> &Option<GpsNavigator> {
        &self.gps_navigator
    }
}

use crate::components::{CarType, Engine, GpsNavigator, Transmission};

pub struct Manual {
    car_type: CarType,
    seats: u16,
    engine: Engine,
    transmission: Transmission,
    gps_navigator: Option<GpsNavigator>,
}

impl Manual {
    pub fn new(
        car_type: CarType,
        seats: u16,
        engine: Engine,
        transmission: Transmission,
        gps_navigator: Option<GpsNavigator>,
    ) -> Self {
        Self {
            car_type,
            seats,
            engine,
            transmission,
            gps_navigator,
        }
    }
}

impl std::fmt::Display for Manual {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        writeln!(f, "Type of car: {:?}", self.car_type)?;
        writeln!(f, "Count of seats: {}", self.seats)?;
        writeln!(
            f,
            "Engine: volume - {}; mileage - {}",
            self.engine.volume(),
            self.engine.mileage()
        )?;
        writeln!(f, "Transmission: {:?}", self.transmission)?;
        match self.gps_navigator {
            Some(_) => writeln!(f, "GPS Navigator: Functional")?,
            None => writeln!(f, "GPS Navigator: N/A")?,
        };
        Ok(())
    }
}

#[derive(Copy, Clone, Debug)]
pub enum CarType {
    CityCar,
    SportsCar,
    Suv,
}

#[derive(Debug)]
pub enum Transmission {
    SingleSpeed,
    Manual,
    Automatic,
    SemiAutomatic,
}

pub struct Engine {
    volume: f64,
    mileage: f64,
    started: bool,
}

impl Engine {
    pub fn new(volume: f64, mileage: f64) -> Self {
        Self {
            volume,
            mileage,
            started: false,
        }
    }

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

    pub fn off(&mut self) {
        self.started = false;
    }

    pub fn started(&self) -> bool {
        self.started
    }

    pub fn volume(&self) -> f64 {
        self.volume
    }

    pub fn mileage(&self) -> f64 {
        self.mileage
    }

    pub fn go(&mut self, mileage: f64) {
        if self.started() {
            self.mileage += mileage;
        } else {
            println!("Cannot go(), you must start engine first!");
        }
    }
}

pub struct GpsNavigator {
    route: String,
}

impl GpsNavigator {
    pub fn new() -> Self {
        Self::from_route(
            "221b, Baker Street, London  to Scotland Yard, 8-10 Broadway, London".into(),
        )
    }

    pub fn from_route(route: String) -> Self {
        Self { route }
    }

    pub fn route(&self) -> &String {
        &self.route
    }
}

use crate::{
    builders::Builder,
    components::{CarType, Engine, GpsNavigator, Transmission},
};

/// يعرف المُوجّه كيفية بناء سيارة.
///
/// ومع ذلك، يمكن للبنّاء بناء دليل سيارة بدلًا من سيارة فعلية،
/// كل شيء يعتمد على البنّاء المحدد.
pub struct Director;

impl Director {
    pub fn construct_sports_car(builder: &mut impl Builder) {
        builder.set_car_type(CarType::SportsCar);
        builder.set_seats(2);
        builder.set_engine(Engine::new(3.0, 0.0));
        builder.set_transmission(Transmission::SemiAutomatic);
        builder.set_gps_navigator(GpsNavigator::new());
    }

    pub fn construct_city_car(builder: &mut impl Builder) {
        builder.set_car_type(CarType::CityCar);
        builder.set_seats(2);
        builder.set_engine(Engine::new(1.2, 0.0));
        builder.set_transmission(Transmission::Automatic);
        builder.set_gps_navigator(GpsNavigator::new());
    }

    pub fn construct_suv(builder: &mut impl Builder) {
        builder.set_car_type(CarType::Suv);
        builder.set_seats(4);
        builder.set_engine(Engine::new(2.5, 0.0));
        builder.set_transmission(Transmission::Manual);
        builder.set_gps_navigator(GpsNavigator::new());
    }
}

#![allow(unused)]

mod builders;
mod cars;
mod components;
mod director;

use builders::{Builder, CarBuilder, CarManualBuilder};
use cars::{Car, Manual};
use director::Director;

fn main() {
    let mut car_builder = CarBuilder::default();

    // يحصل المُوجّه على كائن البنّاء المحدد من العميل
    // (كود التطبيق). لأن التطبيق يعلم أي بنّاء
    // يجب استخدامه للحصول على منتج معين.
    Director::construct_sports_car(&mut car_builder);

    // غالبًا ما يُسترد المنتج النهائي من كائن البنّاء، إذ
    // لا يعلم المُوجّه ولا يعتمد على البنّاؤين المحددين
    // والمنتجات.
    let car: Car = car_builder.build();
    println!("Car built: {:?}\n", car.car_type());

    let mut manual_builder = CarManualBuilder::default();

    // قد يعرف المُوجّه عدة وصفات بناء.
    Director::construct_city_car(&mut manual_builder);

    // The final car manual.
    let manual: Manual = manual_builder.build();
    println!("Car manual built:\n{}", manual);
}

Car built: SportsCar

Car manual built:
Type of car: CityCar
Count of seats: 2
Engine: volume - 1.2; mileage - 0
Transmission: Automatic
GPS Navigator: Functional
```

### swift

```swift
import XCTest

/// تُحدّد واجهة Builder التوابع الخاصة بإنشاء الأجزاء المختلفة
/// من كائنات المنتج.
protocol Builder {

    func producePartA()
    func producePartB()
    func producePartC()
}

/// تتبع فئات البنّاء المحدد واجهة Builder وتوفر تطبيقات محددة
/// لخطوات البناء. قد يكون لديك عدة تنوعات من البنّاؤين
/// مُطبَّقة بشكل مختلف في برنامجك.
class ConcreteBuilder1: Builder {

    /// يجب أن يحتوي نموذج البنّاء الجديد على كائن منتج فارغ يُستخدم
    /// في عملية التجميع اللاحقة.
    private var product = Product1()

    func reset() {
        product = Product1()
    }

    /// جميع خطوات الإنتاج تعمل مع نفس نموذج المنتج.
    func producePartA() {
        product.add(part: "PartA1")
    }

    func producePartB() {
        product.add(part: "PartB1")
    }

    func producePartC() {
        product.add(part: "PartC1")
    }

    /// من المفترض أن يوفر البنّاؤون المحددون توابعهم الخاصة لاسترداد النتائج.
    /// لأن أنواعًا مختلفة من البنّاؤين قد تُنشئ منتجات مختلفة تمامًا
    /// لا تتبع نفس الواجهة. لذلك لا يمكن الإعلان عن هذه التوابع
    /// في واجهة Builder الأساسية (على الأقل في لغات البرمجة ذات الأنواع الستاتيكية).
    ///
    /// عادةً، بعد إعادة النتيجة النهائية إلى العميل، يُتوقع من نموذج البنّاء
    /// أن يكون جاهزًا لبدء إنتاج منتج آخر. لهذا السبب من الشائع
    /// استدعاء تابع reset في نهاية جسم تابع `getProduct`.
    /// ومع ذلك، هذا السلوك ليس إلزاميًا، ويمكنك جعل البنّاؤين ينتظرون
    /// استدعاء reset صريحًا من كود العميل قبل التخلص من النتيجة السابقة.
    func retrieveProduct() -> Product1 {
        let result = self.product
        reset()
        return result
    }
}

/// المُوجّه مسؤول فقط عن تنفيذ خطوات البناء بتسلسل معين.
/// يفيد ذلك عند إنتاج منتجات وفق ترتيب أو تهيئة محددة.
/// بالمعنى الدقيق، فئة المُوجّه اختيارية إذ يمكن للعميل
/// التحكم في البنّاؤين مباشرةً.
class Director {

    private var builder: Builder?

    /// يعمل المُوجّه مع أي نموذج بنّاء يُمرّره إليه كود العميل.
    /// بهذه الطريقة يمكن لكود العميل تغيير النوع النهائي للمنتج المُجمَّع حديثًا.
    func update(builder: Builder) {
        self.builder = builder
    }

    /// يمكن للمُوجّه بناء عدة تنوعات من المنتج باستخدام نفس خطوات البناء.
    func buildMinimalViableProduct() {
        builder?.producePartA()
    }

    func buildFullFeaturedProduct() {
        builder?.producePartA()
        builder?.producePartB()
        builder?.producePartC()
    }
}

/// استخدام نمط Builder منطقي فقط عندما تكون منتجاتك معقدةً جدًا
/// وتتطلب تهيئةً مكثفة.
///
/// على خلاف أنماط الإنشاء الأخرى، يمكن للبنّاؤين المحددين المختلفين إنتاج
/// منتجات غير مرتبطة. بمعنى آخر، نتائج البنّاؤين المختلفين قد لا تتبع
/// دائمًا نفس الواجهة.
class Product1 {

    private var parts = [String]()

    func add(part: String) {
        self.parts.append(part)
    }

    func listParts() -> String {
        return "Product parts: " + parts.joined(separator: ", ") + "\n"
    }
}

/// يُنشئ كود العميل كائن البنّاء ويُمرّره إلى المُوجّه ثم يُطلق
/// عملية البناء. يُسترد الناتج النهائي من كائن البنّاء.
class Client {
    // ...
    static func someClientCode(director: Director) {
        let builder = ConcreteBuilder1()
        director.update(builder: builder)
        
        print("Standard basic product:")
        director.buildMinimalViableProduct()
        print(builder.retrieveProduct().listParts())

        print("Standard full featured product:")
        director.buildFullFeaturedProduct()
        print(builder.retrieveProduct().listParts())

        // تذكّر، يمكن استخدام نمط Builder دون فئة مُوجّه.
        print("Custom product:")
        builder.producePartA()
        builder.producePartC()
        print(builder.retrieveProduct().listParts())
    }
    // ...
}

/// لنرى كيف يتلاقى كل شيء.
class BuilderConceptual: XCTestCase {

    func testBuilderConceptual() {
        let director = Director()
        Client.someClientCode(director: director)
    }
}

Standard basic product:
Product parts: PartA1

Standard full featured product:
Product parts: PartA1, PartB1, PartC1

Custom product:
Product parts: PartA1, PartC1

import Foundation
import XCTest


class BaseQueryBuilder<Model: DomainModel> {

    typealias Predicate = (Model) -> (Bool)

    func limit(_ limit: Int) -> BaseQueryBuilder<Model> {
        return self
    }

    func filter(_ predicate: @escaping Predicate) -> BaseQueryBuilder<Model> {
        return self
    }

    func fetch() -> [Model] {
        preconditionFailure("Should be overridden in subclasses.")
    }
}

class RealmQueryBuilder<Model: DomainModel>: BaseQueryBuilder<Model> {

    enum Query {
        case filter(Predicate)
        case limit(Int)
        /// ...
    }

    fileprivate var operations = [Query]()

    @discardableResult
    override func limit(_ limit: Int) -> RealmQueryBuilder<Model> {
        operations.append(Query.limit(limit))
        return self
    }

    @discardableResult
    override func filter(_ predicate: @escaping Predicate) -> RealmQueryBuilder<Model> {
        operations.append(Query.filter(predicate))
        return self
    }

    override func fetch() -> [Model] {
        print("RealmQueryBuilder: Initializing RealmDataProvider with \(operations.count) operations:")
        return RealmProvider().fetch(operations)
    }
}

class CoreDataQueryBuilder<Model: DomainModel>: BaseQueryBuilder<Model> {

    enum Query {
        case filter(Predicate)
        case limit(Int)
        case includesPropertyValues(Bool)
        /// ...
    }

    fileprivate var operations = [Query]()

    override func limit(_ limit: Int) -> CoreDataQueryBuilder<Model> {
        operations.append(Query.limit(limit))
        return self
    }

    override func filter(_ predicate: @escaping Predicate) -> CoreDataQueryBuilder<Model> {
        operations.append(Query.filter(predicate))
        return self
    }

    func includesPropertyValues(_ toggle: Bool) -> CoreDataQueryBuilder<Model> {
        operations.append(Query.includesPropertyValues(toggle))
        return self
    }

    override func fetch() -> [Model] {
        print("CoreDataQueryBuilder: Initializing CoreDataProvider with \(operations.count) operations.")
        return CoreDataProvider().fetch(operations)
    }
}


/// تحتوي موفرات البيانات على منطق جلب النماذج. يراكم البنّاؤون
/// العمليات ثم يُحدّثون الموفرين لجلب البيانات.

class RealmProvider {

    func fetch<Model: DomainModel>(_ operations: [RealmQueryBuilder<Model>.Query]) -> [Model] {

        print("RealmProvider: Retrieving data from Realm...")

        for item in operations {
            switch item {
            case .filter(_):
                print("RealmProvider: executing the 'filter' operation.")
                /// استخدام نموذج Realm لتصفية النتائج.
                break
            case .limit(_):
                print("RealmProvider: executing the 'limit' operation.")
                /// استخدام نموذج Realm لتقييد النتائج.
                break
            }
        }

        /// Return results from Realm
        return []
    }
}

class CoreDataProvider {

    func fetch<Model: DomainModel>(_ operations: [CoreDataQueryBuilder<Model>.Query]) -> [Model] {

        /// إنشاء NSFetchRequest

        print("CoreDataProvider: Retrieving data from CoreData...")

        for item in operations {
            switch item {
            case .filter(_):
                print("CoreDataProvider: executing the 'filter' operation.")
                /// ضبط 'predicate' لـ NSFetchRequest.
                break
            case .limit(_):
                print("CoreDataProvider: executing the 'limit' operation.")
                /// ضبط 'fetchLimit' لـ NSFetchRequest.
                break
            case .includesPropertyValues(_):
                print("CoreDataProvider: executing the 'includesPropertyValues' operation.")
                /// ضبط 'includesPropertyValues' لـ NSFetchRequest.
                break
            }
        }

        /// تنفيذ NSFetchRequest وإعادة النتائج.
        return []
    }
}


protocol DomainModel {
    /// يُجمّع البروتوكول نماذج المجال في واجهة مشتركة
}

private struct User: DomainModel {
    let id: Int
    let age: Int
    let email: String
}


class BuilderRealWorld: XCTestCase {

    func testBuilderRealWorld() {
        print("Client: Start fetching data from Realm")
        clientCode(builder: RealmQueryBuilder<User>())

        print()

        print("Client: Start fetching data from CoreData")
        clientCode(builder: CoreDataQueryBuilder<User>())
    }

    fileprivate func clientCode(builder: BaseQueryBuilder<User>) {

        let results = builder.filter({ $0.age < 20 })
            .limit(1)
            .fetch()

        print("Client: I have fetched: " + String(results.count) + " records.")
    }
}

Client: Start fetching data from Realm
RealmQueryBuilder: Initializing RealmDataProvider with 2 operations:
RealmProvider: Retrieving data from Realm...
RealmProvider: executing the 'filter' operation.
RealmProvider: executing the 'limit' operation.
Client: I have fetched: 0 records.

Client: Start fetching data from CoreData
CoreDataQueryBuilder: Initializing CoreDataProvider with 2 operations.
CoreDataProvider: Retrieving data from CoreData...
CoreDataProvider: executing the 'filter' operation.
CoreDataProvider: executing the 'limit' operation.
Client: I have fetched: 0 records.
```

### typescript

```typescript
/**
 * تُحدّد واجهة Builder التوابع الخاصة بإنشاء الأجزاء المختلفة
 * من كائنات المنتج.
 */
interface Builder {
    producePartA(): void;
    producePartB(): void;
    producePartC(): void;
}

/**
 * تتبع فئات البنّاء المحدد واجهة Builder وتوفر تطبيقات محددة
 * لخطوات البناء. قد يكون لديك عدة تنوعات من البنّاؤين
 * مُطبَّقة بشكل مختلف في برنامجك.
 */
class ConcreteBuilder1 implements Builder {
    private product: Product1;

    /**
     * يجب أن يحتوي نموذج البنّاء الجديد على كائن منتج فارغ يُستخدم
     * في عملية التجميع اللاحقة.
     */
    constructor() {
        this.reset();
    }

    public reset(): void {
        this.product = new Product1();
    }

    /**
     * جميع خطوات الإنتاج تعمل مع نفس نموذج المنتج.
     */
    public producePartA(): void {
        this.product.parts.push('PartA1');
    }

    public producePartB(): void {
        this.product.parts.push('PartB1');
    }

    public producePartC(): void {
        this.product.parts.push('PartC1');
    }

    /**
     * من المفترض أن يوفر البنّاؤون المحددون توابعهم الخاصة لاسترداد النتائج.
     * لأن أنواعًا مختلفة من البنّاؤين قد تُنشئ منتجات مختلفة تمامًا
     * لا تتبع نفس الواجهة. لذلك لا يمكن الإعلان عن هذه التوابع
     * في واجهة Builder الأساسية (على الأقل في لغات البرمجة ذات الأنواع الستاتيكية).
     *
     * عادةً، بعد إعادة النتيجة النهائية إلى العميل، يُتوقع من نموذج البنّاء
     * أن يكون جاهزًا لبدء إنتاج منتج آخر. لهذا السبب من الشائع
     * استدعاء تابع reset في نهاية جسم تابع `getProduct`.
     * ومع ذلك، هذا السلوك ليس إلزاميًا، ويمكنك جعل البنّاؤين ينتظرون
     * استدعاء reset صريحًا من كود العميل قبل التخلص من النتيجة السابقة.
     */
    public getProduct(): Product1 {
        const result = this.product;
        this.reset();
        return result;
    }
}

/**
 * استخدام نمط Builder منطقي فقط عندما تكون منتجاتك معقدةً جدًا
 * وتتطلب تهيئةً مكثفة.
 *
 * على خلاف أنماط الإنشاء الأخرى، يمكن للبنّاؤين المحددين المختلفين إنتاج
 * منتجات غير مرتبطة. بمعنى آخر، نتائج البنّاؤين المختلفين قد لا تتبع
 * دائمًا نفس الواجهة.
 */
class Product1 {
    public parts: string[] = [];

    public listParts(): void {
        console.log(`Product parts: ${this.parts.join(', ')}\n`);
    }
}

/**
 * المُوجّه مسؤول فقط عن تنفيذ خطوات البناء بتسلسل معين.
 * يفيد ذلك عند إنتاج منتجات وفق ترتيب أو تهيئة محددة.
 * بالمعنى الدقيق، فئة المُوجّه اختيارية إذ يمكن للعميل
 * التحكم في البنّاؤين مباشرةً.
 */
class Director {
    private builder: Builder;

    /**
     * يعمل المُوجّه مع أي نموذج بنّاء يُمرّره إليه كود العميل.
     * بهذه الطريقة يمكن لكود العميل تغيير النوع النهائي للمنتج المُجمَّع حديثًا.
     */
    public setBuilder(builder: Builder): void {
        this.builder = builder;
    }

    /**
     * يمكن للمُوجّه بناء عدة تنوعات من المنتج باستخدام نفس خطوات البناء.
     */
    public buildMinimalViableProduct(): void {
        this.builder.producePartA();
    }

    public buildFullFeaturedProduct(): void {
        this.builder.producePartA();
        this.builder.producePartB();
        this.builder.producePartC();
    }
}

/**
 * يُنشئ كود العميل كائن البنّاء ويُمرّره إلى المُوجّه ثم يُطلق
 * عملية البناء. يُسترد الناتج النهائي من كائن البنّاء.
 */
function clientCode(director: Director) {
    const builder = new ConcreteBuilder1();
    director.setBuilder(builder);

    console.log('Standard basic product:');
    director.buildMinimalViableProduct();
    builder.getProduct().listParts();

    console.log('Standard full featured product:');
    director.buildFullFeaturedProduct();
    builder.getProduct().listParts();

    // تذكّر، يمكن استخدام نمط Builder دون فئة مُوجّه.
    console.log('Custom product:');
    builder.producePartA();
    builder.producePartC();
    builder.getProduct().listParts();
}

const director = new Director();
clientCode(director);

Standard basic product:
Product parts: PartA1

Standard full featured product:
Product parts: PartA1, PartB1, PartC1

Custom product:
Product parts: PartA1, PartC1
```

