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

> طريقة المصنع هي نمط تصميم إنشائي يوفّر واجهة لإنشاء الكائنات في الصنف الأعلى (superclass)، لكنه يسمح للأصناف الفرعية بتغيير نوع الكائنات التي سيتم إنشاؤها.

## Intent

**طريقة المصنع** هي نمط تصميم إنشائي يوفّر واجهة لإنشاء الكائنات في الصنف الأعلى (superclass)، لكنه يسمح للأصناف الفرعية بتغيير نوع الكائنات التي سيتم إنشاؤها.

## Problem

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

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

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

أخبار رائعة، أليس كذلك؟ لكن ماذا عن الكود؟ في الوقت الحالي، يرتبط معظم كودك بالصنف `Truck`. وإضافة `Ships` إلى التطبيق ستتطلب إجراء تغييرات على قاعدة الكود بأكملها. علاوة على ذلك، إذا قررت لاحقًا إضافة نوع آخر من النقل إلى التطبيق، فستحتاج على الأرجح إلى إجراء كل هذه التغييرات مرة أخرى.

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

## Solution

يقترح نمط طريقة المصنع أن تستبدل استدعاءات إنشاء الكائنات المباشرة (باستخدام العامل `new`) باستدعاءات لطريقة _مصنع_ خاصة. لا تقلق: لا تزال الكائنات تُنشأ عبر العامل `new`، لكنه يُستدعى من داخل طريقة المصنع. وكثيرًا ما يُشار إلى الكائنات التي تُرجعها طريقة المصنع باسم _المنتجات._

يمكن للأصناف الفرعية تغيير صنف الكائنات التي تُرجعها طريقة المصنع.

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

هناك قيد بسيط رغم ذلك: لا يمكن للأصناف الفرعية إرجاع أنواع مختلفة من المنتجات إلا إذا كانت هذه المنتجات تشترك في صنف أساسي أو واجهة مشتركة. كذلك ينبغي أن يكون نوع الإرجاع لطريقة المصنع في الصنف الأساسي معلَنًا على أنه هذه الواجهة.

يجب أن تتبع جميع المنتجات الواجهة نفسها.

على سبيل المثال، ينبغي أن ينفّذ كلا الصنفين `Truck` و`Ship` الواجهة `Transport`، التي تُعلن عن طريقة تُدعى `deliver`. وينفّذ كل صنف هذه الطريقة بشكل مختلف: فالشاحنات توصّل البضائع برًا، والسفن توصّل البضائع بحرًا. وتُرجع طريقة المصنع في الصنف `RoadLogistics` كائنات شاحنات، بينما تُرجع طريقة المصنع في الصنف `SeaLogistics` سفنًا.

طالما أن جميع أصناف المنتجات تنفّذ واجهة مشتركة، يمكنك تمرير كائناتها إلى كود العميل دون كسره.

الكود الذي يستخدم طريقة المصنع (الذي يُسمى غالبًا كود _العميل_) لا يرى فرقًا بين المنتجات الفعلية التي تُرجعها مختلف الأصناف الفرعية. فالعميل يتعامل مع جميع المنتجات على أنها `Transport` مجردة. ويعلم العميل أنه يُفترض في جميع كائنات النقل أن تمتلك طريقة `deliver`، لكن كيفية عملها بالضبط ليست مهمة بالنسبة إلى العميل.

## Structure

1. يُعلن **المنتج** عن الواجهة المشتركة بين جميع الكائنات التي يمكن أن ينتجها المُنشئ وأصنافه الفرعية.
2. **المنتجات الملموسة** هي تنفيذات مختلفة لواجهة المنتج.
3. يُعلن صنف **المُنشئ** عن طريقة المصنع التي تُرجع كائنات منتج جديدة. ومن المهم أن يتطابق نوع الإرجاع لهذه الطريقة مع واجهة المنتج.
يمكنك إعلان طريقة المصنع على أنها `abstract` لإجبار جميع الأصناف الفرعية على تنفيذ نسخها الخاصة من الطريقة. وكبديل، يمكن لطريقة المصنع الأساسية أن تُرجع نوع منتج افتراضيًا.
لاحظ أنه على الرغم من اسمه، فإن إنشاء المنتجات **ليس** المسؤولية الأساسية للمُنشئ. فعادةً ما يمتلك صنف المُنشئ بالفعل بعض منطق العمل الأساسي المتعلق بالمنتجات. وتساعد طريقة المصنع على فصل هذا المنطق عن أصناف المنتجات الملموسة. وإليك تشبيهًا: قد يكون لدى شركة كبيرة لتطوير البرمجيات قسم تدريب للمبرمجين. ومع ذلك، تظل الوظيفة الأساسية للشركة ككل هي كتابة الكود، لا إنتاج المبرمجين.
4. تتجاوز **المُنشئات الملموسة** طريقة المصنع الأساسية بحيث تُرجع نوعًا مختلفًا من المنتج.
لاحظ أن طريقة المصنع ليست مضطرة إلى **إنشاء** نسخ جديدة في كل مرة. يمكنها أيضًا إرجاع كائنات موجودة من ذاكرة تخزين مؤقت (cache) أو مجمّع كائنات (object pool) أو مصدر آخر.

## Pseudocode

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

مثال مربع الحوار متعدد المنصّات.

يستخدم الصنف الأساسي `Dialog` عناصر واجهة مستخدم مختلفة لعرض نافذته. وقد تبدو هذه العناصر مختلفة قليلًا تحت أنظمة تشغيل مختلفة، لكن ينبغي أن تتصرف بشكل متّسق. فالزر في Windows لا يزال زرًا في Linux.

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

لكي يعمل هذا النمط، يجب أن يتعامل الصنف الأساسي `Dialog` مع أزرار مجردة: صنف أساسي أو واجهة تتبعها جميع الأزرار الملموسة. بهذه الطريقة يظل الكود داخل `Dialog` فعّالًا أيًّا كان نوع الأزرار التي يتعامل معها.

بالطبع، يمكنك تطبيق هذا النهج على عناصر واجهة المستخدم الأخرى أيضًا. غير أنك مع كل طريقة مصنع جديدة تضيفها إلى `Dialog`، تقترب أكثر من نمط [المصنع المجرد](/ar/design-patterns/abstract-factory). لا تقلق، سنتحدث عن هذا النمط لاحقًا.

// يُعلن صنف المُنشئ عن طريقة المصنع التي يجب أن
// تُرجع كائنًا من صنف منتج. عادةً ما توفّر الأصناف
// الفرعية للمُنشئ تنفيذ هذه الطريقة.
class Dialog is
    // قد يوفّر المُنشئ أيضًا تنفيذًا افتراضيًا
    // لطريقة المصنع.
    abstract method createButton():Button

    // لاحظ أنه على الرغم من اسمه، فإن المسؤولية
    // الأساسية للمُنشئ ليست إنشاء المنتجات. فهو عادةً
    // يحتوي على بعض منطق العمل الأساسي الذي يعتمد على
    // كائنات المنتج التي تُرجعها طريقة المصنع. ويمكن
    // للأصناف الفرعية أن تغيّر منطق العمل ذاك بشكل غير
    // مباشر عبر تجاوز طريقة المصنع وإرجاع نوع مختلف من
    // المنتج منها.
    method render() is
        // استدعِ طريقة المصنع لإنشاء كائن منتج.
        Button okButton = createButton()
        // الآن استخدم المنتج.
        okButton.onClick(closeDialog)
        okButton.render()

// تتجاوز المُنشئات الملموسة طريقة المصنع لتغيير
// نوع المنتج الناتج.
class WindowsDialog extends Dialog is
    method createButton():Button is
        return new WindowsButton()

class WebDialog extends Dialog is
    method createButton():Button is
        return new HTMLButton()

// تُعلن واجهة المنتج عن العمليات التي يجب أن
// تنفّذها جميع المنتجات الملموسة.
interface Button is
    method render()
    method onClick(f)

// توفّر المنتجات الملموسة تنفيذات متنوعة
// لواجهة المنتج.
class WindowsButton implements Button is
    method render(a, b) is
        // عرض زر بنمط Windows.
    method onClick(f) is
        // ربط حدث نقر أصلي لنظام التشغيل.

class HTMLButton implements Button is
    method render(a, b) is
        // إرجاع تمثيل HTML للزر.
    method onClick(f) is
        // ربط حدث نقر لمتصفح الويب.

class Application is
    field dialog: Dialog

    // يختار التطبيق نوع المُنشئ بناءً على الإعدادات
    // أو إعدادات البيئة الحالية.
    method initialize() is
        config = readApplicationConfigFile()

        if (config.OS == "Windows") then
            dialog = new WindowsDialog()
        else if (config.OS == "Web") then
            dialog = new WebDialog()
        else
            throw new Exception("Error! Unknown operating system.")

    // يعمل كود العميل مع نسخة من مُنشئ ملموس، وإن
    // كان ذلك عبر واجهته الأساسية. وطالما ظل العميل
    // يتعامل مع المُنشئ عبر الواجهة الأساسية، يمكنك
    // تمرير أي صنف فرعي من المُنشئ إليه.
    method main() is
        this.initialize()
        dialog.render()

## Applicability

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

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

على سبيل المثال، لإضافة نوع منتج جديد إلى التطبيق، ستحتاج فقط إلى إنشاء صنف فرعي جديد من المُنشئ (creator) وتجاوز (override) طريقة المصنع فيه.

 استخدم طريقة المصنع عندما تريد أن توفر لمستخدمي مكتبتك أو إطار العمل الخاص بك وسيلة لتوسيع مكوناته الداخلية.

 ربما تكون الوراثة هي أسهل طريقة لتوسيع السلوك الافتراضي لمكتبة أو إطار عمل. لكن كيف سيتعرّف إطار العمل على أن صنفك الفرعي هو الذي ينبغي استخدامه بدلًا من المكوّن القياسي؟

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

لنرَ كيف يعمل ذلك. تخيّل أنك تكتب تطبيقًا باستخدام إطار عمل واجهة مستخدم مفتوح المصدر. يجب أن يحتوي تطبيقك على أزرار دائرية، لكن إطار العمل لا يوفّر سوى أزرار مربعة. تقوم بتوسيع الصنف القياسي `Button` بصنف فرعي رائع هو `RoundButton`. لكنك الآن بحاجة إلى إخبار الصنف الرئيسي `UIFramework` باستخدام صنف الزر الفرعي الجديد بدلًا من الصنف الافتراضي.

لتحقيق ذلك، تنشئ صنفًا فرعيًا `UIWithRoundButtons` من صنف أساسي في إطار العمل وتتجاوز طريقته `createButton`. وبينما تُرجع هذه الطريقة كائنات `Button` في الصنف الأساسي، تجعل صنفك الفرعي يُرجع كائنات `RoundButton`. والآن استخدم الصنف `UIWithRoundButtons` بدلًا من `UIFramework`. وهذا كل ما في الأمر!

 استخدم طريقة المصنع عندما تريد توفير موارد النظام عبر إعادة استخدام الكائنات الموجودة بدلًا من إعادة بنائها في كل مرة.

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

لنفكّر فيما يجب فعله لإعادة استخدام كائن موجود:

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

هذا قدر كبير من الكود! ويجب وضعه كله في مكان واحد حتى لا تلوّث البرنامج بكود مكرر.

ربما يكون المكان الأكثر وضوحًا وملاءمة لوضع هذا الكود هو مُنشئ (constructor) الصنف الذي نحاول إعادة استخدام كائناته. غير أن المُنشئ يجب أن يُرجع دائمًا **كائنات جديدة** بحكم تعريفه. ولا يمكنه إرجاع نسخ موجودة مسبقًا.

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

## How to Implement

1. اجعل جميع المنتجات تتبع الواجهة نفسها. ينبغي أن تُعلن هذه الواجهة عن طرق منطقية في كل منتج.
2. أضف طريقة مصنع فارغة داخل صنف المُنشئ. ينبغي أن يتطابق نوع الإرجاع للطريقة مع واجهة المنتج المشتركة.
3. في كود المُنشئ، ابحث عن جميع الإشارات إلى مُنشئات المنتجات. استبدلها واحدًا تلو الآخر باستدعاءات لطريقة المصنع، مع استخراج كود إنشاء المنتج إلى طريقة المصنع.
قد تحتاج إلى إضافة معامل مؤقت إلى طريقة المصنع للتحكم في نوع المنتج المُرجَع.
في هذه المرحلة، قد يبدو كود طريقة المصنع قبيحًا للغاية. فقد يحتوي على جملة `switch` كبيرة تختار صنف المنتج الذي سيُنشأ. لكن لا تقلق، سنُصلح ذلك قريبًا.
4. الآن، أنشئ مجموعة من الأصناف الفرعية للمُنشئ لكل نوع من المنتجات المدرجة في طريقة المصنع. تجاوز طريقة المصنع في الأصناف الفرعية واستخرج الأجزاء المناسبة من كود البناء من الطريقة الأساسية.
5. إذا كان هناك عدد كبير جدًا من أنواع المنتجات ولم يكن من المنطقي إنشاء أصناف فرعية لها جميعًا، يمكنك إعادة استخدام معامل التحكم من الصنف الأساسي في الأصناف الفرعية.
على سبيل المثال، تخيّل أن لديك التسلسل الهرمي التالي من الأصناف: الصنف الأساسي `Mail` مع صنفين فرعيين: `AirMail` و`GroundMail`؛ وأصناف `Transport` هي `Plane` و`Truck` و`Train`. وبينما يستخدم الصنف `AirMail` كائنات `Plane` فقط، قد يعمل `GroundMail` مع كائنات `Truck` و`Train` معًا. يمكنك إنشاء صنف فرعي جديد (لِنَقُل `TrainMail`) للتعامل مع الحالتين، لكن هناك خيار آخر. يمكن لكود العميل تمرير وسيط إلى طريقة المصنع في الصنف `GroundMail` للتحكم في المنتج الذي يريد الحصول عليه.
6. إذا أصبحت طريقة المصنع الأساسية فارغة بعد كل عمليات الاستخراج، يمكنك جعلها مجردة. وإذا بقي شيء فيها، يمكنك جعله سلوكًا افتراضيًا للطريقة.

## Pros

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

## Cons

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

## Relations with Other Patterns

* تبدأ العديد من التصميمات باستخدام [طريقة المصنع](/ar/design-patterns/factory-method) (أقل تعقيدًا وأكثر قابلية للتخصيص عبر الأصناف الفرعية) ثم تتطور نحو [المصنع المجرد](/ar/design-patterns/abstract-factory) أو [النموذج الأولي](/ar/design-patterns/prototype) أو [الباني](/ar/design-patterns/builder) (أكثر مرونة، لكن أكثر تعقيدًا).
* غالبًا ما تستند أصناف [المصنع المجرد](/ar/design-patterns/abstract-factory) إلى مجموعة من [طرق المصنع](/ar/design-patterns/factory-method)، لكن يمكنك أيضًا استخدام [النموذج الأولي](/ar/design-patterns/prototype) لتأليف الطرق في هذه الأصناف.
* يمكنك استخدام [طريقة المصنع](/ar/design-patterns/factory-method) مع [المُكرِّر](/ar/design-patterns/iterator) للسماح لأصناف المجموعات الفرعية بإرجاع أنواع مختلفة من المُكرِّرات المتوافقة مع المجموعات.
* لا يستند [النموذج الأولي](/ar/design-patterns/prototype) إلى الوراثة، لذا فهو لا يعاني من عيوبها. ومن ناحية أخرى، يتطلب _النموذج الأولي_ تهيئة معقدة للكائن المستنسخ. أما [طريقة المصنع](/ar/design-patterns/factory-method) فتستند إلى الوراثة لكنها لا تتطلب خطوة تهيئة.
* [طريقة المصنع](/ar/design-patterns/factory-method) هي تخصيص لـ [طريقة القالب](/ar/design-patterns/template-method). وفي الوقت نفسه، قد تكون _طريقة المصنع_ بمثابة خطوة ضمن _طريقة قالب_ كبيرة.

## Extra

* اقرأ [مقارنة المصانع](/ar/design-patterns/factory-comparison) إذا لم تستطع التمييز بين مختلف أنماط المصانع ومفاهيمها.
## Relations

**Related patterns**

- [المصنع المجرد (Abstract Factory)](/ar/design-patterns/abstract-factory.md)
- [النموذج الأولي (Prototype)](/ar/design-patterns/prototype.md)
- [البنّاء](/ar/design-patterns/builder.md)
- [المُكرِّر](/ar/design-patterns/iterator.md)
- [أسلوب القالب](/ar/design-patterns/template-method.md)

## Code Examples

### java

```java
package refactoring_guru.factory_method.example.buttons;

/**
 * واجهة مشتركة لجميع الأزرار.
 */
public interface Button {
    void render();
    void onClick();
}

package refactoring_guru.factory_method.example.buttons;

/**
 * تنفيذ زر HTML.
 */
public class HtmlButton implements Button {

    public void render() {
        System.out.println("<button>Test Button</button>");
        onClick();
    }

    public void onClick() {
        System.out.println("Click! Button says - 'Hello World!'");
    }
}

package refactoring_guru.factory_method.example.buttons;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

/**
 * تنفيذ زر Windows.
 */
public class WindowsButton implements Button {
    JPanel panel = new JPanel();
    JFrame frame = new JFrame();
    JButton button;

    public void render() {
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JLabel label = new JLabel("Hello World!");
        label.setOpaque(true);
        label.setBackground(new Color(235, 233, 126));
        label.setFont(new Font("Dialog", Font.BOLD, 44));
        label.setHorizontalAlignment(SwingConstants.CENTER);
        panel.setLayout(new FlowLayout(FlowLayout.CENTER));
        frame.getContentPane().add(panel);
        panel.add(label);
        onClick();
        panel.add(button);

        frame.setSize(320, 200);
        frame.setVisible(true);
        onClick();
    }

    public void onClick() {
        button = new JButton("Exit");
        button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                frame.setVisible(false);
                System.exit(0);
            }
        });
    }
}

package refactoring_guru.factory_method.example.factory;

import refactoring_guru.factory_method.example.buttons.Button;

/**
 * صنف المصنع الأساسي. لاحظ أن «المصنع» مجرد دور للصنف. ينبغي أن يحتوي على بعض
 * منطق العمل الأساسي الذي يحتاج إلى إنشاء منتجات مختلفة.
 */
public abstract class Dialog {

    public void renderWindow() {
        // ... كود آخر ...

        Button okButton = createButton();
        okButton.render();
    }

    /**
     * ستتجاوز الأصناف الفرعية هذه الطريقة من أجل إنشاء كائنات أزرار محددة.
     */
    public abstract Button createButton();
}

package refactoring_guru.factory_method.example.factory;

import refactoring_guru.factory_method.example.buttons.Button;
import refactoring_guru.factory_method.example.buttons.HtmlButton;

/**
 * سيُنتج مربع حوار HTML أزرار HTML.
 */
public class HtmlDialog extends Dialog {

    @Override
    public Button createButton() {
        return new HtmlButton();
    }
}

package refactoring_guru.factory_method.example.factory;

import refactoring_guru.factory_method.example.buttons.Button;
import refactoring_guru.factory_method.example.buttons.WindowsButton;

/**
 * سيُنتج مربع حوار Windows أزرار Windows.
 */
public class WindowsDialog extends Dialog {

    @Override
    public Button createButton() {
        return new WindowsButton();
    }
}

package refactoring_guru.factory_method.example;

import refactoring_guru.factory_method.example.factory.Dialog;
import refactoring_guru.factory_method.example.factory.HtmlDialog;
import refactoring_guru.factory_method.example.factory.WindowsDialog;

/**
 * صنف العرض التوضيحي. كل شيء يجتمع هنا.
 */
public class Demo {
    private static Dialog dialog;

    public static void main(String[] args) {
        configure();
        runBusinessLogic();
    }

    /**
     * عادةً ما يتم اختيار المصنع الملموس بناءً على خيارات الإعدادات أو البيئة.
     */
    static void configure() {
        if (System.getProperty("os.name").equals("Windows 10")) {
            dialog = new WindowsDialog();
        } else {
            dialog = new HtmlDialog();
        }
    }

    /**
     * ينبغي أن يعمل كل كود العميل مع المصانع والمنتجات عبر واجهات مجردة. بهذه
     * الطريقة لا يهتم بأي مصنع يعمل معه ولا بنوع المنتج الذي يُرجعه.
     */
    static void runBusinessLogic() {
        dialog.renderWindow();
    }
}

<button>Test Button</button>
Click! Button says - 'Hello World!'
```

### csharp

```csharp
using System;

namespace RefactoringGuru.DesignPatterns.FactoryMethod.Conceptual
{
    // يُعلن صنف المُنشئ (Creator) عن طريقة المصنع التي يُفترض أن تُرجع
    // كائنًا من صنف المنتج (Product). عادةً ما توفّر الأصناف الفرعية للمُنشئ
    // تنفيذ هذه الطريقة.
    abstract class Creator
    {
        // لاحظ أن المُنشئ قد يوفّر أيضًا تنفيذًا افتراضيًا لطريقة
        // المصنع.
        public abstract IProduct FactoryMethod();

        // لاحظ أيضًا أنه على الرغم من اسمه، فإن المسؤولية الأساسية
        // للمُنشئ ليست إنشاء المنتجات. فهو عادةً يحتوي على بعض
        // منطق العمل الأساسي الذي يعتمد على كائنات المنتج التي تُرجعها
        // طريقة المصنع. ويمكن للأصناف الفرعية أن تغيّر منطق العمل ذاك
        // بشكل غير مباشر عبر تجاوز طريقة المصنع وإرجاع نوع مختلف من
        // المنتج منها.
        public string SomeOperation()
        {
            // استدعِ طريقة المصنع لإنشاء كائن منتج.
            var product = FactoryMethod();
            // الآن، استخدم المنتج.
            var result = "Creator: The same creator's code has just worked with "
                + product.Operation();

            return result;
        }
    }

    // تتجاوز المُنشئات الملموسة طريقة المصنع من أجل تغيير
    // نوع المنتج الناتج.
    class ConcreteCreator1 : Creator
    {
        // لاحظ أن توقيع الطريقة لا يزال يستخدم نوع المنتج المجرد،
        // رغم أن المنتج الملموس هو ما يُرجَع فعليًا من الطريقة. بهذه
        // الطريقة يمكن للمُنشئ أن يبقى مستقلًا عن أصناف المنتجات
        // الملموسة.
        public override IProduct FactoryMethod()
        {
            return new ConcreteProduct1();
        }
    }

    class ConcreteCreator2 : Creator
    {
        public override IProduct FactoryMethod()
        {
            return new ConcreteProduct2();
        }
    }

    // تُعلن واجهة المنتج عن العمليات التي يجب أن تنفّذها جميع
    // المنتجات الملموسة.
    public interface IProduct
    {
        string Operation();
    }

    // توفّر المنتجات الملموسة تنفيذات متنوعة لواجهة
    // المنتج.
    class ConcreteProduct1 : IProduct
    {
        public string Operation()
        {
            return "{Result of ConcreteProduct1}";
        }
    }

    class ConcreteProduct2 : IProduct
    {
        public string Operation()
        {
            return "{Result of ConcreteProduct2}";
        }
    }

    class Client
    {
        public void Main()
        {
            Console.WriteLine("App: Launched with the ConcreteCreator1.");
            ClientCode(new ConcreteCreator1());
            
            Console.WriteLine("");

            Console.WriteLine("App: Launched with the ConcreteCreator2.");
            ClientCode(new ConcreteCreator2());
        }

        // يعمل كود العميل مع نسخة من مُنشئ ملموس، وإن كان ذلك
        // عبر واجهته الأساسية. وطالما ظل العميل يتعامل مع
        // المُنشئ عبر الواجهة الأساسية، يمكنك تمرير أي صنف فرعي
        // من المُنشئ إليه.
        public void ClientCode(Creator creator)
        {
            // ...
            Console.WriteLine("Client: I'm not aware of the creator's class," +
                "but it still works.\n" + creator.SomeOperation());
            // ...
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            new Client().Main();
        }
    }
}

App: Launched with the ConcreteCreator1.
Client: I'm not aware of the creator's class, but it still works.
Creator: The same creator's code has just worked with {Result of ConcreteProduct1}

App: Launched with the ConcreteCreator2.
Client: I'm not aware of the creator's class, but it still works.
Creator: The same creator's code has just worked with {Result of ConcreteProduct2}
```

### cpp

```cpp
/**
 * تُعلن واجهة المنتج عن العمليات التي يجب أن تنفّذها جميع المنتجات
 * الملموسة.
 */

class Product {
 public:
  virtual ~Product() {}
  virtual std::string Operation() const = 0;
};

/**
 * توفّر المنتجات الملموسة تنفيذات متنوعة لواجهة المنتج.
 */
class ConcreteProduct1 : public Product {
 public:
  std::string Operation() const override {
    return "{Result of the ConcreteProduct1}";
  }
};
class ConcreteProduct2 : public Product {
 public:
  std::string Operation() const override {
    return "{Result of the ConcreteProduct2}";
  }
};

/**
 * يُعلن صنف المُنشئ (Creator) عن طريقة المصنع التي يُفترض أن تُرجع كائنًا
 * من صنف المنتج (Product). عادةً ما توفّر الأصناف الفرعية للمُنشئ تنفيذ
 * هذه الطريقة.
 */

class Creator {
  /**
   * لاحظ أن المُنشئ قد يوفّر أيضًا تنفيذًا افتراضيًا لطريقة
   * المصنع.
   */
 public:
  virtual ~Creator(){};
  virtual Product* FactoryMethod() const = 0;
  /**
   * لاحظ أيضًا أنه على الرغم من اسمه، فإن المسؤولية الأساسية للمُنشئ ليست
   * إنشاء المنتجات. فهو عادةً يحتوي على بعض منطق العمل الأساسي الذي يعتمد
   * على كائنات المنتج التي تُرجعها طريقة المصنع. ويمكن للأصناف الفرعية أن
   * تغيّر منطق العمل ذاك بشكل غير مباشر عبر تجاوز طريقة المصنع وإرجاع نوع
   * مختلف من المنتج منها.
   */

  std::string SomeOperation() const {
    // استدعِ طريقة المصنع لإنشاء كائن منتج.
    Product* product = this->FactoryMethod();
    // الآن، استخدم المنتج.
    std::string result = "Creator: The same creator's code has just worked with " + product->Operation();
    delete product;
    return result;
  }
};

/**
 * تتجاوز المُنشئات الملموسة طريقة المصنع من أجل تغيير نوع المنتج
 * الناتج.
 */
class ConcreteCreator1 : public Creator {
  /**
   * لاحظ أن توقيع الطريقة لا يزال يستخدم نوع المنتج المجرد، رغم أن المنتج
   * الملموس هو ما يُرجَع فعليًا من الطريقة. بهذه الطريقة يمكن للمُنشئ أن
   * يبقى مستقلًا عن أصناف المنتجات الملموسة.
   */
 public:
  Product* FactoryMethod() const override {
    return new ConcreteProduct1();
  }
};

class ConcreteCreator2 : public Creator {
 public:
  Product* FactoryMethod() const override {
    return new ConcreteProduct2();
  }
};

/**
 * يعمل كود العميل مع نسخة من مُنشئ ملموس، وإن كان ذلك عبر واجهته
 * الأساسية. وطالما ظل العميل يتعامل مع المُنشئ عبر الواجهة الأساسية،
 * يمكنك تمرير أي صنف فرعي من المُنشئ إليه.
 */
void ClientCode(const Creator& creator) {
  // ...
  std::cout << "Client: I'm not aware of the creator's class, but it still works.\n"
            << creator.SomeOperation() << std::endl;
  // ...
}

/**
 * يختار التطبيق نوع المُنشئ بناءً على الإعدادات أو البيئة.
 */

int main() {
  std::cout << "App: Launched with the ConcreteCreator1.\n";
  Creator* creator = new ConcreteCreator1();
  ClientCode(*creator);
  std::cout << std::endl;
  std::cout << "App: Launched with the ConcreteCreator2.\n";
  Creator* creator2 = new ConcreteCreator2();
  ClientCode(*creator2);

  delete creator;
  delete creator2;
  return 0;
}

App: Launched with the ConcreteCreator1.
Client: I'm not aware of the creator's class, but it still works.
Creator: The same creator's code has just worked with {Result of the ConcreteProduct1}

App: Launched with the ConcreteCreator2.
Client: I'm not aware of the creator's class, but it still works.
Creator: The same creator's code has just worked with {Result of the ConcreteProduct2}
```

### go

```go
package main

type IGun interface {
	setName(name string)
	setPower(power int)
	getName() string
	getPower() int
}

package main

type Gun struct {
	name  string
	power int
}

func (g *Gun) setName(name string) {
	g.name = name
}

func (g *Gun) getName() string {
	return g.name
}

func (g *Gun) setPower(power int) {
	g.power = power
}

func (g *Gun) getPower() int {
	return g.power
}

package main

type Ak47 struct {
	Gun
}

func newAk47() IGun {
	return &Ak47{
		Gun: Gun{
			name:  "AK47 gun",
			power: 4,
		},
	}
}

package main

type musket struct {
	Gun
}

func newMusket() IGun {
	return &musket{
		Gun: Gun{
			name:  "Musket gun",
			power: 1,
		},
	}
}

package main

import "fmt"

func getGun(gunType string) (IGun, error) {
	if gunType == "ak47" {
		return newAk47(), nil
	}
	if gunType == "musket" {
		return newMusket(), nil
	}
	return nil, fmt.Errorf("Wrong gun type passed")
}

package main

import "fmt"

func main() {
	ak47, _ := getGun("ak47")
	musket, _ := getGun("musket")

	printDetails(ak47)
	printDetails(musket)
}

func printDetails(g IGun) {
	fmt.Printf("Gun: %s", g.getName())
	fmt.Println()
	fmt.Printf("Power: %d", g.getPower())
	fmt.Println()
}

Gun: AK47 gun
Power: 4
Gun: Musket gun
Power: 1
```

### php

```php
<?php

namespace RefactoringGuru\FactoryMethod\Conceptual;

/**
 * يُعلن صنف المُنشئ (Creator) عن طريقة المصنع التي يُفترض أن تُرجع كائنًا
 * من صنف المنتج (Product). عادةً ما توفّر الأصناف الفرعية للمُنشئ تنفيذ
 * هذه الطريقة.
 */
abstract class Creator
{
    /**
     * لاحظ أن المُنشئ قد يوفّر أيضًا تنفيذًا افتراضيًا لطريقة
     * المصنع.
     */
    abstract public function factoryMethod(): Product;

    /**
     * لاحظ أيضًا أنه على الرغم من اسمه، فإن المسؤولية الأساسية للمُنشئ ليست
     * إنشاء المنتجات. فهو عادةً يحتوي على بعض منطق العمل الأساسي الذي يعتمد
     * على كائنات المنتج التي تُرجعها طريقة المصنع. ويمكن للأصناف الفرعية أن
     * تغيّر منطق العمل ذاك بشكل غير مباشر عبر تجاوز طريقة المصنع وإرجاع نوع
     * مختلف من المنتج منها.
     */
    public function someOperation(): string
    {
        // استدعِ طريقة المصنع لإنشاء كائن منتج.
        $product = $this->factoryMethod();
        // الآن، استخدم المنتج.
        $result = "Creator: The same creator's code has just worked with " .
            $product->operation();

        return $result;
    }
}

/**
 * تتجاوز المُنشئات الملموسة طريقة المصنع من أجل تغيير نوع المنتج
 * الناتج.
 */
class ConcreteCreator1 extends Creator
{
    /**
     * لاحظ أن توقيع الطريقة لا يزال يستخدم نوع المنتج المجرد، رغم أن المنتج
     * الملموس هو ما يُرجَع فعليًا من الطريقة. بهذه الطريقة يمكن للمُنشئ أن
     * يبقى مستقلًا عن أصناف المنتجات الملموسة.
     */
    public function factoryMethod(): Product
    {
        return new ConcreteProduct1();
    }
}

class ConcreteCreator2 extends Creator
{
    public function factoryMethod(): Product
    {
        return new ConcreteProduct2();
    }
}

/**
 * تُعلن واجهة المنتج عن العمليات التي يجب أن تنفّذها جميع المنتجات
 * الملموسة.
 */
interface Product
{
    public function operation(): string;
}

/**
 * توفّر المنتجات الملموسة تنفيذات متنوعة لواجهة المنتج.
 */
class ConcreteProduct1 implements Product
{
    public function operation(): string
    {
        return "{Result of the ConcreteProduct1}";
    }
}

class ConcreteProduct2 implements Product
{
    public function operation(): string
    {
        return "{Result of the ConcreteProduct2}";
    }
}

/**
 * يعمل كود العميل مع نسخة من مُنشئ ملموس، وإن كان ذلك عبر واجهته
 * الأساسية. وطالما ظل العميل يتعامل مع المُنشئ عبر الواجهة الأساسية،
 * يمكنك تمرير أي صنف فرعي من المُنشئ إليه.
 */
function clientCode(Creator $creator)
{
    // ...
    echo "Client: I'm not aware of the creator's class, but it still works.\n"
        . $creator->someOperation();
    // ...
}

/**
 * يختار التطبيق نوع المُنشئ بناءً على الإعدادات أو البيئة.
 */
echo "App: Launched with the ConcreteCreator1.\n";
clientCode(new ConcreteCreator1());
echo "\n\n";

echo "App: Launched with the ConcreteCreator2.\n";
clientCode(new ConcreteCreator2());

App: Launched with the ConcreteCreator1.
Client: I'm not aware of the creator's class, but it still works.
Creator: The same creator's code has just worked with {Result of the ConcreteProduct1}

App: Launched with the ConcreteCreator2.
Client: I'm not aware of the creator's class, but it still works.
Creator: The same creator's code has just worked with {Result of the ConcreteProduct2}

<?php

namespace RefactoringGuru\FactoryMethod\RealWorld;

/**
 * يُعلن المُنشئ عن طريقة مصنع يمكن استخدامها بديلًا عن استدعاءات المُنشئ
 * المباشرة للمنتجات، على سبيل المثال:
 *
 * - قبل: $p = new FacebookConnector();
 * - بعد: $p = $this->getSocialNetwork;
 *
 * يسمح هذا بتغيير نوع المنتج الذي تنشئه الأصناف الفرعية
 * لـ SocialNetworkPoster.
 */
abstract class SocialNetworkPoster
{
    /**
     * طريقة المصنع الفعلية. لاحظ أنها تُرجع الموصِّل المجرد. وهذا يتيح
     * للأصناف الفرعية إرجاع أي موصّلات ملموسة دون كسر عقد الصنف الأعلى.
     */
    abstract public function getSocialNetwork(): SocialNetworkConnector;

    /**
     * عندما تُستخدم طريقة المصنع داخل منطق عمل المُنشئ، يمكن للأصناف
     * الفرعية تغيير المنطق بشكل غير مباشر عبر إرجاع أنواع مختلفة من
     * الموصّل من طريقة المصنع.
     */
    public function post($content): void
    {
        // استدعِ طريقة المصنع لإنشاء كائن منتج...
        $network = $this->getSocialNetwork();
        // ...ثم استخدمه كما تشاء.
        $network->logIn();
        $network->createPost($content);
        $network->logout();
    }
}

/**
 * يدعم هذا المُنشئ الملموس فيسبوك. تذكّر أن هذا الصنف يرث أيضًا طريقة
 * 'post' من الصنف الأب. المُنشئات الملموسة هي الأصناف التي يستخدمها
 * العميل فعليًا.
 */
class FacebookPoster extends SocialNetworkPoster
{
    private $login, $password;

    public function __construct(string $login, string $password)
    {
        $this->login = $login;
        $this->password = $password;
    }

    public function getSocialNetwork(): SocialNetworkConnector
    {
        return new FacebookConnector($this->login, $this->password);
    }
}

/**
 * يدعم هذا المُنشئ الملموس لينكدإن.
 */
class LinkedInPoster extends SocialNetworkPoster
{
    private $email, $password;

    public function __construct(string $email, string $password)
    {
        $this->email = $email;
        $this->password = $password;
    }

    public function getSocialNetwork(): SocialNetworkConnector
    {
        return new LinkedInConnector($this->email, $this->password);
    }
}

/**
 * تُعلن واجهة المنتج عن سلوكيات أنواع مختلفة من المنتجات.
 */
interface SocialNetworkConnector
{
    public function logIn(): void;

    public function logOut(): void;

    public function createPost($content): void;
}

/**
 * ينفّذ هذا المنتج الملموس واجهة برمجة تطبيقات فيسبوك.
 */
class FacebookConnector implements SocialNetworkConnector
{
    private $login, $password;

    public function __construct(string $login, string $password)
    {
        $this->login = $login;
        $this->password = $password;
    }

    public function logIn(): void
    {
        echo "Send HTTP API request to log in user $this->login with " .
            "password $this->password\n";
    }

    public function logOut(): void
    {
        echo "Send HTTP API request to log out user $this->login\n";
    }

    public function createPost($content): void
    {
        echo "Send HTTP API requests to create a post in Facebook timeline.\n";
    }
}

/**
 * ينفّذ هذا المنتج الملموس واجهة برمجة تطبيقات لينكدإن.
 */
class LinkedInConnector implements SocialNetworkConnector
{
    private $email, $password;

    public function __construct(string $email, string $password)
    {
        $this->email = $email;
        $this->password = $password;
    }

    public function logIn(): void
    {
        echo "Send HTTP API request to log in user $this->email with " .
            "password $this->password\n";
    }

    public function logOut(): void
    {
        echo "Send HTTP API request to log out user $this->email\n";
    }

    public function createPost($content): void
    {
        echo "Send HTTP API requests to create a post in LinkedIn timeline.\n";
    }
}

/**
 * يمكن لكود العميل أن يعمل مع أي صنف فرعي من SocialNetworkPoster لأنه
 * لا يعتمد على الأصناف الملموسة.
 */
function clientCode(SocialNetworkPoster $creator)
{
    // ...
    $creator->post("Hello world!");
    $creator->post("I had a large hamburger this morning!");
    // ...
}

/**
 * أثناء مرحلة التهيئة، يمكن للتطبيق أن يقرر شبكة التواصل الاجتماعي التي
 * يريد العمل معها، وأن ينشئ كائنًا من الصنف الفرعي المناسب، ويمرره إلى
 * كود العميل.
 */
echo "Testing ConcreteCreator1:\n";
clientCode(new FacebookPoster("john_smith", "******"));
echo "\n\n";

echo "Testing ConcreteCreator2:\n";
clientCode(new LinkedInPoster("john_smith@example.com", "******"));

Testing ConcreteCreator1:
Send HTTP API request to log in user john_smith with password ******
Send HTTP API requests to create a post in Facebook timeline.
Send HTTP API request to log out user john_smith
Send HTTP API request to log in user john_smith with password ******
Send HTTP API requests to create a post in Facebook timeline.
Send HTTP API request to log out user john_smith


Testing ConcreteCreator2:
Send HTTP API request to log in user john_smith@example.com with password ******
Send HTTP API requests to create a post in LinkedIn timeline.
Send HTTP API request to log out user john_smith@example.com
Send HTTP API request to log in user john_smith@example.com with password ******
Send HTTP API requests to create a post in LinkedIn timeline.
Send HTTP API request to log out user john_smith@example.com
```

### python

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


class Creator(ABC):
    """
    يُعلن صنف المُنشئ (Creator) عن طريقة المصنع التي يُفترض أن تُرجع كائنًا
    من صنف المنتج (Product). عادةً ما توفّر الأصناف الفرعية للمُنشئ تنفيذ
    هذه الطريقة.
    """

    @abstractmethod
    def factory_method(self):
        """
        لاحظ أن المُنشئ قد يوفّر أيضًا تنفيذًا افتراضيًا لطريقة
        المصنع.
        """
        pass

    def some_operation(self) -> str:
        """
        لاحظ أيضًا أنه على الرغم من اسمه، فإن المسؤولية الأساسية للمُنشئ
        ليست إنشاء المنتجات. فهو عادةً يحتوي على بعض منطق العمل الأساسي
        الذي يعتمد على كائنات المنتج التي تُرجعها طريقة المصنع. ويمكن
        للأصناف الفرعية أن تغيّر منطق العمل ذاك بشكل غير مباشر عبر تجاوز
        طريقة المصنع وإرجاع نوع مختلف من المنتج منها.
        """

        # استدعِ طريقة المصنع لإنشاء كائن منتج.
        product = self.factory_method()

        # الآن، استخدم المنتج.
        result = f"Creator: The same creator's code has just worked with {product.operation()}"

        return result


"""
تتجاوز المُنشئات الملموسة طريقة المصنع من أجل تغيير نوع المنتج الناتج.
"""


class ConcreteCreator1(Creator):
    """
    لاحظ أن توقيع الطريقة لا يزال يستخدم نوع المنتج المجرد، رغم أن المنتج
    الملموس هو ما يُرجَع فعليًا من الطريقة. بهذه الطريقة يمكن للمُنشئ أن
    يبقى مستقلًا عن أصناف المنتجات الملموسة.
    """

    def factory_method(self) -> Product:
        return ConcreteProduct1()


class ConcreteCreator2(Creator):
    def factory_method(self) -> Product:
        return ConcreteProduct2()


class Product(ABC):
    """
    تُعلن واجهة المنتج عن العمليات التي يجب أن تنفّذها جميع المنتجات
    الملموسة.
    """

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


"""
توفّر المنتجات الملموسة تنفيذات متنوعة لواجهة المنتج.
"""


class ConcreteProduct1(Product):
    def operation(self) -> str:
        return "{Result of the ConcreteProduct1}"


class ConcreteProduct2(Product):
    def operation(self) -> str:
        return "{Result of the ConcreteProduct2}"


def client_code(creator: Creator) -> None:
    """
    يعمل كود العميل مع نسخة من مُنشئ ملموس، وإن كان ذلك عبر واجهته
    الأساسية. وطالما ظل العميل يتعامل مع المُنشئ عبر الواجهة الأساسية،
    يمكنك تمرير أي صنف فرعي من المُنشئ إليه.
    """

    print(f"Client: I'm not aware of the creator's class, but it still works.\n"
          f"{creator.some_operation()}", end="")


if __name__ == "__main__":
    print("App: Launched with the ConcreteCreator1.")
    client_code(ConcreteCreator1())
    print("\n")

    print("App: Launched with the ConcreteCreator2.")
    client_code(ConcreteCreator2())

App: Launched with the ConcreteCreator1.
Client: I'm not aware of the creator's class, but it still works.
Creator: The same creator's code has just worked with {Result of the ConcreteProduct1}

App: Launched with the ConcreteCreator2.
Client: I'm not aware of the creator's class, but it still works.
Creator: The same creator's code has just worked with {Result of the ConcreteProduct2}
```

### ruby

```ruby
# يُعلن صنف المُنشئ (Creator) عن طريقة المصنع التي يُفترض أن تُرجع كائنًا
# من صنف المنتج (Product). عادةً ما توفّر الأصناف الفرعية للمُنشئ تنفيذ
# هذه الطريقة.
class Creator
  # لاحظ أن المُنشئ قد يوفّر أيضًا تنفيذًا افتراضيًا لطريقة
  # المصنع.
  def factory_method
    raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
  end

  # لاحظ أيضًا أنه على الرغم من اسمه، فإن المسؤولية الأساسية للمُنشئ ليست
  # إنشاء المنتجات. فهو عادةً يحتوي على بعض منطق العمل الأساسي الذي يعتمد
  # على كائنات المنتج التي تُرجعها طريقة المصنع. ويمكن للأصناف الفرعية أن
  # تغيّر منطق العمل ذاك بشكل غير مباشر عبر تجاوز طريقة المصنع وإرجاع نوع
  # مختلف من المنتج منها.
  def some_operation
    # استدعِ طريقة المصنع لإنشاء كائن منتج.
    product = factory_method

    # الآن، استخدم المنتج.
    "Creator: The same creator's code has just worked with #{product.operation}"
  end
end

# تتجاوز المُنشئات الملموسة طريقة المصنع من أجل تغيير نوع المنتج
# الناتج.
class ConcreteCreator1 < Creator
  # لاحظ أن توقيع الطريقة لا يزال يستخدم نوع المنتج المجرد، رغم أن المنتج
  # الملموس هو ما يُرجَع فعليًا من الطريقة. بهذه الطريقة يمكن للمُنشئ أن
  # يبقى مستقلًا عن أصناف المنتجات الملموسة.
  def factory_method
    ConcreteProduct1.new
  end
end

class ConcreteCreator2 < Creator
  # @return [ConcreteProduct2]
  def factory_method
    ConcreteProduct2.new
  end
end

# تُعلن واجهة المنتج عن العمليات التي يجب أن تنفّذها جميع المنتجات
# الملموسة.
class Product
  # return [String]
  def operation
    raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
  end
end

# توفّر المنتجات الملموسة تنفيذات متنوعة لواجهة المنتج.
class ConcreteProduct1 < Product
  # @return [String]
  def operation
    '{Result of the ConcreteProduct1}'
  end
end

class ConcreteProduct2 < Product
  # @return [String]
  def operation
    '{Result of the ConcreteProduct2}'
  end
end

# يعمل كود العميل مع نسخة من مُنشئ ملموس، وإن كان ذلك عبر واجهته
# الأساسية. وطالما ظل العميل يتعامل مع المُنشئ عبر الواجهة الأساسية،
# يمكنك تمرير أي صنف فرعي من المُنشئ إليه.
def client_code(creator)
  print "Client: I'm not aware of the creator's class, but it still works.\n"\
        "#{creator.some_operation}"
end

puts 'App: Launched with the ConcreteCreator1.'
client_code(ConcreteCreator1.new)
puts "\n\n"

puts 'App: Launched with the ConcreteCreator2.'
client_code(ConcreteCreator2.new)

App: Launched with the ConcreteCreator1.
Client: I'm not aware of the creator's class, but it still works.
Creator: The same creator's code has just worked with {Result of the ConcreteProduct1}

App: Launched with the ConcreteCreator2.
Client: I'm not aware of the creator's class, but it still works.
Creator: The same creator's code has just worked with {Result of the ConcreteProduct2}
```

### rust

```rust
pub trait Button {
    fn render(&self);
    fn on_click(&self);
}

/// يمتلك مربع الحوار (Dialog) طريقة مصنع `create_button`.
///
/// تنشئ أزرارًا مختلفة بحسب تنفيذ المصنع.
pub trait Dialog {
    /// طريقة المصنع. يجب تجاوزها بتنفيذ ملموس.
    fn create_button(&self) -> Box<dyn Button>;

    fn render(&self) {
        let button = self.create_button();
        button.render();
    }

    fn refresh(&self) {
        println!("Dialog - Refresh");
    }
}

use crate::gui::{Button, Dialog};

pub struct HtmlButton;

impl Button for HtmlButton {
    fn render(&self) {
        println!("<button>Test Button</button>");
        self.on_click();
    }

    fn on_click(&self) {
        println!("Click! Button says - 'Hello World!'");
    }
}

pub struct HtmlDialog;

impl Dialog for HtmlDialog {
    /// تنشئ زر HTML.
    fn create_button(&self) -> Box<dyn Button> {
        Box::new(HtmlButton)
    }
}

use crate::gui::{Button, Dialog};

pub struct WindowsButton;

impl Button for WindowsButton {
    fn render(&self) {
        println!("Drawing a Windows button");
        self.on_click();
    }

    fn on_click(&self) {
        println!("Click! Hello, Windows!");
    }
}

pub struct WindowsDialog;

impl Dialog for WindowsDialog {
    /// تنشئ زر Windows.
    fn create_button(&self) -> Box<dyn Button> {
        Box::new(WindowsButton)
    }
}

use crate::gui::Dialog;
use crate::html_gui::HtmlDialog;
use crate::windows_gui::WindowsDialog;

pub fn initialize() -> &'static dyn Dialog {
    // يتم اختيار نوع مربع الحوار بناءً على إعدادات البيئة أو الإعدادات.
    if cfg!(windows) {
        println!("-- Windows detected, creating Windows GUI --");
        &WindowsDialog
    } else {
        println!("-- No OS detected, creating the HTML GUI --");
        &HtmlDialog
    }
}

mod gui;
mod html_gui;
mod init;
mod windows_gui;

use init::initialize;

fn main() {
    // لا تعتمد بقية الكود على أنواع مربعات حوار محددة، لأنها
    // تعمل مع جميع كائنات مربع الحوار عبر السمة (trait) المجردة `Dialog`
    // المعرّفة في الوحدة `gui`.
    let dialog = initialize();
    dialog.render();
    dialog.refresh();
}

<button>Test Button</button>
Click! Button says - 'Hello World!'
Dialog - Refresh

/// غرفة متاهة سيتم إنشاؤها عبر طريقة مصنع.
pub trait Room {
    fn render(&self);
}

/// تمتلك لعبة المتاهة طريقة مصنع تُنتج غرفًا مختلفة.
pub trait MazeGame {
    type RoomImpl: Room;

    /// طريقة مصنع.
    fn rooms(&self) -> Vec<Self::RoomImpl>;

    fn play(&self) {
        for room in self.rooms() {
            room.render();
        }
    }
}

/// يقوم كود العميل بتهيئة الموارد وإجراء تحضيرات أخرى
/// ثم يستخدم مصنعًا لبناء اللعبة وتشغيلها.
pub fn run(maze_game: impl MazeGame) {
    println!("Loading resources...");
    println!("Starting the game...");

    maze_game.play();
}

use super::game::{MazeGame, Room};

#[derive(Clone)]
pub struct MagicRoom {
    title: String,
}

impl MagicRoom {
    pub fn new(title: String) -> Self {
        Self { title }
    }
}

impl Room for MagicRoom {
    fn render(&self) {
        println!("Magic Room: {}", self.title);
    }
}

pub struct MagicMaze {
    rooms: Vec<MagicRoom>,
}

impl MagicMaze {
    pub fn new() -> Self {
        Self {
            rooms: vec![
                MagicRoom::new("Infinite Room".into()),
                MagicRoom::new("Red Room".into()),
            ],
        }
    }
}

impl MazeGame for MagicMaze {
    type RoomImpl = MagicRoom;

    fn rooms(&self) -> Vec<Self::RoomImpl> {
        self.rooms.clone()
    }
}

use super::game::{MazeGame, Room};

#[derive(Clone)]
pub struct OrdinaryRoom {
    id: u32,
}

impl OrdinaryRoom {
    pub fn new(id: u32) -> Self {
        Self { id }
    }
}

impl Room for OrdinaryRoom {
    fn render(&self) {
        println!("Ordinary Room: #{}", self.id);
    }
}

pub struct OrdinaryMaze {
    rooms: Vec<OrdinaryRoom>,
}

impl OrdinaryMaze {
    pub fn new() -> Self {
        Self {
            rooms: vec![OrdinaryRoom::new(1), OrdinaryRoom::new(2)],
        }
    }
}

impl MazeGame for OrdinaryMaze {
    type RoomImpl = OrdinaryRoom;

    fn rooms(&self) -> Vec<Self::RoomImpl> {
        let mut rooms = self.rooms.clone();
        rooms.reverse();
        rooms
    }
}

mod game;
mod magic_maze;
mod ordinary_maze;

use magic_maze::MagicMaze;
use ordinary_maze::OrdinaryMaze;

/// تعمل اللعبة بمتاهات مختلفة بحسب نوع المصنع الملموس:
/// فهي إما متاهة عادية أو متاهة سحرية.
///
/// لأغراض العرض التوضيحي، تُستخدم كلتا المتاهتين لبناء اللعبة.
fn main() {
    // الخيار 1: تبدأ اللعبة بمتاهة عادية.
    let ordinary_maze = OrdinaryMaze::new();
    game::run(ordinary_maze);

    // الخيار 2: تبدأ اللعبة بمتاهة سحرية.
    let magic_maze = MagicMaze::new();
    game::run(magic_maze);
}

Loading resources...
Starting the game...
Magic Room: Infinite Room
Magic Room: Red Room
Loading resources...
Starting the game...
Ordinary Room: #2
Ordinary Room: #1
```

### swift

```swift
import XCTest

/// يُعلن بروتوكول المُنشئ (Creator) عن طريقة المصنع التي يُفترض أن تُرجع
/// كائنًا جديدًا من صنف المنتج (Product). عادةً ما توفّر الأصناف الفرعية
/// للمُنشئ تنفيذ هذه الطريقة.
protocol Creator {

    /// لاحظ أن المُنشئ قد يوفّر أيضًا تنفيذًا افتراضيًا لطريقة
    /// المصنع.
    func factoryMethod() -> Product

    /// لاحظ أيضًا أنه على الرغم من اسمه، فإن المسؤولية الأساسية للمُنشئ
    /// ليست إنشاء المنتجات. فهو عادةً يحتوي على بعض منطق العمل الأساسي
    /// الذي يعتمد على كائنات المنتج التي تُرجعها طريقة المصنع. ويمكن
    /// للأصناف الفرعية أن تغيّر منطق العمل ذاك بشكل غير مباشر عبر تجاوز
    /// طريقة المصنع وإرجاع نوع مختلف من المنتج منها.
    func someOperation() -> String
}

/// ينفّذ هذا الامتداد السلوك الافتراضي للمُنشئ. ويمكن تجاوز
/// هذا السلوك في الأصناف الفرعية.
extension Creator {

    func someOperation() -> String {
        // استدعِ طريقة المصنع لإنشاء كائن منتج.
        let product = factoryMethod()

        // الآن، استخدم المنتج.
        return "Creator: The same creator's code has just worked with " + product.operation()
    }
}

/// تتجاوز المُنشئات الملموسة طريقة المصنع من أجل تغيير
/// نوع المنتج الناتج.
class ConcreteCreator1: Creator {

    /// لاحظ أن توقيع الطريقة لا يزال يستخدم نوع المنتج المجرد، رغم أن
    /// المنتج الملموس هو ما يُرجَع فعليًا من الطريقة. بهذه الطريقة يمكن
    /// للمُنشئ أن يبقى مستقلًا عن أصناف المنتجات الملموسة.
    public func factoryMethod() -> Product {
        return ConcreteProduct1()
    }
}

class ConcreteCreator2: Creator {

    public func factoryMethod() -> Product {
        return ConcreteProduct2()
    }
}

/// تُعلن واجهة المنتج (protocol) عن العمليات التي يجب أن تنفّذها جميع
/// المنتجات الملموسة.
protocol Product {

    func operation() -> String
}

/// توفّر المنتجات الملموسة تنفيذات متنوعة لواجهة المنتج (protocol).
class ConcreteProduct1: Product {

    func operation() -> String {
        return "{Result of the ConcreteProduct1}"
    }
}

class ConcreteProduct2: Product {

    func operation() -> String {
        return "{Result of the ConcreteProduct2}"
    }
}


/// يعمل كود العميل مع نسخة من مُنشئ ملموس، وإن كان ذلك عبر بروتوكوله
/// الأساسي. وطالما ظل العميل يتعامل مع المُنشئ عبر البروتوكول الأساسي،
/// يمكنك تمرير أي صنف فرعي من المُنشئ إليه.
class Client {
    // ...
    static func someClientCode(creator: Creator) {
        print("Client: I'm not aware of the creator's class, but it still works.\n"
            + creator.someOperation())
    }
    // ...
}

/// لنرَ كيف يعمل كل ذلك معًا.
class FactoryMethodConceptual: XCTestCase {

    func testFactoryMethodConceptual() {

        /// يختار التطبيق نوع المُنشئ بناءً على
        /// الإعدادات أو البيئة.

        print("App: Launched with the ConcreteCreator1.")
        Client.someClientCode(creator: ConcreteCreator1())

        print("\nApp: Launched with the ConcreteCreator2.")
        Client.someClientCode(creator: ConcreteCreator2())
    }
}

App: Launched with the ConcreteCreator1.
Client: I'm not aware of the creator's class, but it still works.
Creator: The same creator's code has just worked with {Result of the ConcreteProduct1}

App: Launched with the ConcreteCreator2.
Client: I'm not aware of the creator's class, but it still works.
Creator: The same creator's code has just worked with {Result of the ConcreteProduct2}

import XCTest

class FactoryMethodRealWorld: XCTestCase {

    func testFactoryMethodRealWorld() {

        let info = "Very important info of the presentation"

        let clientCode = ClientCode()

        /// عرض المعلومات عبر WiFi
        clientCode.present(info: info, with: WifiFactory())

        /// عرض المعلومات عبر البلوتوث
        clientCode.present(info: info, with: BluetoothFactory())
    }
}

protocol ProjectorFactory {

    func createProjector() -> Projector

    func syncedProjector(with projector: Projector) -> Projector
}

extension ProjectorFactory {

    /// التنفيذ الأساسي لـ ProjectorFactory

    func syncedProjector(with projector: Projector) -> Projector {

        /// كل نسخة تنشئ جهاز عرض خاصًا بها
        let newProjector = createProjector()

        /// مزامنة أجهزة العرض
        newProjector.sync(with: projector)

        return newProjector
    }
}

class WifiFactory: ProjectorFactory {

    func createProjector() -> Projector {
        return WifiProjector()
    }
}

class BluetoothFactory: ProjectorFactory {

    func createProjector() -> Projector {
        return BluetoothProjector()
    }
}

protocol Projector {

    /// واجهة جهاز العرض المجردة

    var currentPage: Int { get }

    func present(info: String)

    func sync(with projector: Projector)

    func update(with page: Int)
}

extension Projector {

    /// التنفيذ الأساسي لطرق Projector

    func sync(with projector: Projector) {
        projector.update(with: currentPage)
    }
}

class WifiProjector: Projector {

    var currentPage = 0

    func present(info: String) {
        print("Info is presented over Wifi: \(info)")
    }

    func update(with page: Int) {
        /// ... تمرير الصفحة عبر اتصال WiFi
        /// ...
        currentPage = page
    }
}

class BluetoothProjector: Projector {

    var currentPage = 0

    func present(info: String) {
        print("Info is presented over Bluetooth: \(info)")
    }

    func update(with page: Int) {
        /// ... تمرير الصفحة عبر اتصال البلوتوث
        /// ...
        currentPage = page
    }
}

private class ClientCode {

    private var currentProjector: Projector?

    func present(info: String, with factory: ProjectorFactory) {

        /// تحقق مما إذا كان كود العميل يعرض شيئًا بالفعل...

        guard let projector = currentProjector else {

            /// المتغير 'currentProjector' يساوي nil. أنشئ جهاز عرض جديدًا
            /// وابدأ العرض.

            let projector = factory.createProjector()
            projector.present(info: info)
            self.currentProjector = projector
            return
        }

        /// كود العميل يمتلك جهاز عرض بالفعل. لنزامن صفحات جهاز العرض القديم
        /// مع الجديد.

        self.currentProjector = factory.syncedProjector(with: projector)
        self.currentProjector?.present(info: info)
    }
}

Info is presented over Wifi: Very important info of the presentation
Info is presented over Bluetooth: Very important info of the presentation
```

### typescript

```typescript
/**
 * يُعلن صنف المُنشئ (Creator) عن طريقة المصنع التي يُفترض أن تُرجع كائنًا
 * من صنف المنتج (Product). عادةً ما توفّر الأصناف الفرعية للمُنشئ تنفيذ
 * هذه الطريقة.
 */
abstract class Creator {
    /**
     * لاحظ أن المُنشئ قد يوفّر أيضًا تنفيذًا افتراضيًا لطريقة
     * المصنع.
     */
    public abstract factoryMethod(): Product;

    /**
     * لاحظ أيضًا أنه على الرغم من اسمه، فإن المسؤولية الأساسية للمُنشئ ليست
     * إنشاء المنتجات. فهو عادةً يحتوي على بعض منطق العمل الأساسي الذي يعتمد
     * على كائنات المنتج التي تُرجعها طريقة المصنع. ويمكن للأصناف الفرعية أن
     * تغيّر منطق العمل ذاك بشكل غير مباشر عبر تجاوز طريقة المصنع وإرجاع نوع
     * مختلف من المنتج منها.
     */
    public someOperation(): string {
        // استدعِ طريقة المصنع لإنشاء كائن منتج.
        const product = this.factoryMethod();
        // الآن، استخدم المنتج.
        return `Creator: The same creator's code has just worked with ${product.operation()}`;
    }
}

/**
 * تتجاوز المُنشئات الملموسة طريقة المصنع من أجل تغيير نوع المنتج
 * الناتج.
 */
class ConcreteCreator1 extends Creator {
    /**
     * لاحظ أن توقيع الطريقة لا يزال يستخدم نوع المنتج المجرد، رغم أن المنتج
     * الملموس هو ما يُرجَع فعليًا من الطريقة. بهذه الطريقة يمكن للمُنشئ أن
     * يبقى مستقلًا عن أصناف المنتجات الملموسة.
     */
    public factoryMethod(): Product {
        return new ConcreteProduct1();
    }
}

class ConcreteCreator2 extends Creator {
    public factoryMethod(): Product {
        return new ConcreteProduct2();
    }
}

/**
 * تُعلن واجهة المنتج عن العمليات التي يجب أن تنفّذها جميع المنتجات
 * الملموسة.
 */
interface Product {
    operation(): string;
}

/**
 * توفّر المنتجات الملموسة تنفيذات متنوعة لواجهة المنتج.
 */
class ConcreteProduct1 implements Product {
    public operation(): string {
        return '{Result of the ConcreteProduct1}';
    }
}

class ConcreteProduct2 implements Product {
    public operation(): string {
        return '{Result of the ConcreteProduct2}';
    }
}

/**
 * يعمل كود العميل مع نسخة من مُنشئ ملموس، وإن كان ذلك عبر واجهته
 * الأساسية. وطالما ظل العميل يتعامل مع المُنشئ عبر الواجهة الأساسية،
 * يمكنك تمرير أي صنف فرعي من المُنشئ إليه.
 */
function clientCode(creator: Creator) {
    // ...
    console.log('Client: I\'m not aware of the creator\'s class, but it still works.');
    console.log(creator.someOperation());
    // ...
}

/**
 * يختار التطبيق نوع المُنشئ بناءً على الإعدادات أو البيئة.
 */
console.log('App: Launched with the ConcreteCreator1.');
clientCode(new ConcreteCreator1());
console.log('');

console.log('App: Launched with the ConcreteCreator2.');
clientCode(new ConcreteCreator2());

App: Launched with the ConcreteCreator1.
Client: I'm not aware of the creator's class, but it still works.
Creator: The same creator's code has just worked with {Result of the ConcreteProduct1}

App: Launched with the ConcreteCreator2.
Client: I'm not aware of the creator's class, but it still works.
Creator: The same creator's code has just worked with {Result of the ConcreteProduct2}
```

