---
title: "مقارنة المصانع"
type: "design-pattern"
slug: "factory-comparison"
url: "http://localhost:3000/ar/design-patterns/factory-comparison.md"
---
# مقارنة المصانع

توضح هذه المقالة الفرق بين:

1. المصنع (Factory)
2. دالة الإنشاء (Creation method)
3. دالة الإنشاء الساكنة (Static creation method) أو (static factory method)
4. المصنع البسيط (Simple factory)
5. نمط [دالة المصنع (Factory Method)](/design-patterns/factory-method)
6. نمط [المصنع المجرد (Abstract Factory)](/design-patterns/abstract-factory)

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

لذا دعونا نحاول معرفة الفرق وحل هذه المشكلة مرة واحدة وإلى الأبد.

## 1\. المصنع (Factory)

**المصنع (Factory)** هو مصطلح غامض يرمز إلى وظيفة أو دالة أو فئة من المفترض أن تنتج شيئاً ما. والأكثر شيوعاً هو أن المصانع تنتج كائنات. ولكنها قد تنتج أيضاً ملفات، أو سجلات في قواعد البيانات، وما إلى ذلك.

على سبيل المثال، يمكن الإشارة عفوياً إلى أي من هذه الأشياء على أنها “مصنع”:

* وظيفة أو دالة تقوم بإنشاء واجهة المستخدم الرسومية (GUI) للبرنامج؛
* فئة تقوم بإنشاء مستخدمين؛
* دالة ساكنة تستدعي منشئ الفئة (constructor) بطريقة معينة؛
* أحد أنماط التصميم الإنشائية (creational design patterns).

عادةً، عندما يقول شخص ما كلمة “مصنع”، فمن المفترض أن يكون المعنى الدقيق واضحاً من السياق. ولكن إذا كان لديك شك، فما عليك سوى الاستفسار. فهناك احتمال أن يكون الكاتب نفسه غير مدرك للفارق.

## 2\. دالة الإنشاء (Creation method)

تُعرّف **دالة الإنشاء (Creation method)** في كتاب [Refactoring To Patterns](https://refactoring.guru/ref-to-patterns-book) بأنها “الدالة التي تقوم بإنشاء الكائنات”. هذا يعني أن كل نتيجة لنمط دالة المصنع هي “دالة إنشاء” ولكن العكس ليس صحيحاً بالضرورة. ويعني هذا أيضاً أنه يمكنك استبدال مصطلح “دالة الإنشاء” بأي مكان يستخدم فيه مارتن فاولر مصطلح “دالة المصنع (factory method)” في كتاب [Refactoring](https://refactoring.guru/ref-book) وحيثما يستخدم جوشوا بلوخ مصطلح “دالة المصنع الساكنة (static factory method)” في كتاب [Effective Java](https://refactoring.guru/effective-java-book).

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

يسمي الكثير من الأشخاص مثل هذه الدوال بـ “دالة المصنع” لمجرد أنها تنتج كائنات جديدة: المنطق هنا مباشر؛ الدالة تنشئ كائنات وبما أن جميع _المصانع_ تنشئ كائنات، فيجب أن تكون هذه الدالة بوضوح _دالة مصنع_. وبطبيعة الحال، هناك الكثير من الارتباك عندما يتعلق الأمر بنمط [دالة المصنع (Factory Method)](/design-patterns/factory-method) الحقيقي.

في المثال التالي، تعتبر `next` دالة إنشاء:

class Number {
    private $value;

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

    public function next() {
        return new Number ($this->value + 1);
    }
}

## 3\. دالة الإنشاء الساكنة (Static creation method)

**دالة الإنشاء الساكنة (Static creation method)** هي دالة إنشاء يتم التصريح عنها كـ `static`. وعبارة أخرى، يمكن استدعاؤها مباشرة على الفئة (class) ولا تتطلب إنشاء كائن منها.

لا ترتبك عندما يسمي شخص ما مثل هذه الدوال بـ “دالة المصنع الساكنة (static factory method)”. هذه مجرد عادة سيئة. فنمط [دالة المصنع (Factory Method)](/design-patterns/factory-method) هو نمط تصميم يعتمد على الوراثة (inheritance). وإذا جعلته `static`، فلن تتمكن بعد الآن من توسيعه في الفئات الفرعية (subclasses)، وهو ما يتعارض مع الغرض من النمط.

عندما تعيد دالة الإنشاء الساكنة كائنات جديدة، فإنها تصبح منشئاً بديلاً (alternative constructor).

قد تكون مفيدة عندما:

* تحتاج إلى وجود عدة منشئات (constructors) مختلفة لأغراض مختلفة ولكن تواقيعها (signatures) متطابقة. على سبيل المثال، وجود كل من `Random(int max)` و `Random(int min)` أمر مستحيل في Java و C++ و C# والعديد من اللغات الأخرى. والحل الأكثر شيوعاً هو إنشاء عدة دوال ساكنة تستدعي المنشئ الافتراضي وتعيين القيم المناسبة بعد ذلك.
* تريد إعادة استخدام كائنات موجودة بالفعل، بدلاً من إنشاء كائنات جديدة (انظر نمط [المفرد (Singleton)](/design-patterns/singleton)). يجب على المنشئات في معظم لغات البرمجة إرجاع نسخ كائنات (instances) جديدة. دالة الإنشاء الساكنة هي حل بديل لهذا القيد. داخل الدالة الساكنة، يمكن للكود الخاص بك تحديد ما إذا كان سيتم إنشاء نسخة جديدة عن طريق استدعاء المنشئ أو إرجاع كائن موجود بالفعل من ذاكرة تخزين مؤقت (cache) ما.

في المثال التالي، تعتبر الدالة `load` دالة إنشاء ساكنة. فهي توفر طريقة ملائمة لاسترجاع المستخدمين من قاعدة البيانات.

class User {
    private $id, $name, $email, $phone;

    public function __construct($id, $name, $email, $phone) {
        $this->id = $id;
        $this->name = $name;
        $this->email = $email;
        $this->phone = $phone;
    }

    public static function load($id) {
        list($id, $name, $email, $phone) = DB::load_data('users', 'id', 'name', 'email', 'phone');
        $user = new User($id, $name, $email, $phone);
        return $user;
    }
}

## 4\. نمط _المصنع البسيط (Simple factory)_

يصف نمط **المصنع البسيط (Simple factory)** مُعرّف في كتاب [Head First Design Patterns](https://refactoring.guru/head-first-book). فئة تحتوي على دالة إنشاء واحدة مع جملة شرطية كبيرة تختار الفئة التي سيتم إنشاء نسخة منها وإرجاعها بناءً على معاملات الدالة.

يخلط الناس عادةً بين _المصانع البسيطة_ وبين _المصانع_ العامة أو أحد أنماط التصميم الإنشائية. في معظم الحالات، يعتبر المصنع البسيط خطوة وسيطة لتقديم نمط [دالة المصنع (Factory Method)](/design-patterns/factory-method) أو نمط [المصنع المجرد (Abstract Factory)](/design-patterns/abstract-factory) الأنماط.

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

بالمناسبة، إذا قمت بالتصريح عن مصنع بسيط على أنه `abstract`، فلن يتحول هذا سحرياً إلى نمط _المصنع المجرد_.

فيما يلي مثال على _المصنع البسيط_:

class UserFactory {
    public static function create($type) {
        switch ($type) {
            case 'user': return new User();
            case 'customer': return new Customer();
            case 'admin': return new Admin();
            default:
                throw new Exception('Wrong user type passed.');
        }
    }
}

## 5\. نمط _دالة المصنع (Factory Method)_

نمط **دالة المصنع (Factory Method)** مُعرّف في كتاب GoF الشهير [Design Patterns: Elements of Reusable Object-Oriented Software](https://refactoring.guru/gof-book). هو نمط تصميم إنشائي يوفر واجهة لإنشاء الكائنات ولكنه يسمح للفئات الفرعية بتعديل نوع الكائن الذي سيتم إنشاؤه.

إذا كان لديك دالة إنشاء في الفئة الأساسية (base class) وفئات فرعية تقوم بتوسيعها، فمن المحتمل أنك تبحث في نمط دالة المصنع.

abstract class Department {
    public abstract function createEmployee($id);

    public function fire($id) {
        $employee = $this->createEmployee($id);
        $employee->paySalary();
        $employee->dismiss();
    }
}

class ITDepartment extends Department {
    public function createEmployee($id) {
        return new Programmer($id);
    }
}

class AccountingDepartment extends Department {
    public function createEmployee($id) {
        return new Accountant($id);
    }
}

## 6\. نمط _المصنع المجرد (Abstract Factory)_

نمط **المصنع المجرد (Abstract Factory)** مُعرّف أيضاً في [كتاب GoF](https://refactoring.guru/gof-book). هو نمط تصميم إنشائي يسمح بإنتاج عائلات من الكائنات المرتبطة أو المعتمدة على بعضها البعض دون تحديد فئاتها الملموسة (concrete classes).

ما هي “عائلات الكائنات”؟ على سبيل المثال، خذ مجموعة الفئات هذه: `Transport` + `Engine` + `Controls`. قد يكون هناك عدة أشكال مختلفة لهذه:

1. `Car` + `CombustionEngine` + `SteeringWheel`
2. `Plane` + `JetEngine` + `Yoke`

إذا كان برنامجك لا يتعامل مع عائلات المنتجات، فلن تحتاج إلى مصنع مجرد.

ومرة أخرى، يخلط الكثير من الناس بين نمط _المصنع المجرد_ وفئة المصنع البسيط المصرح عنها كـ `abstract`. دونت دويت!

### خاتمة

الآن بعد أن عرفت الفرق، ألقِ نظرة جديدة على أنماط التصميم:

* [Factory Method](/design-patterns/factory-method)
* [Abstract Factory](/design-patterns/abstract-factory)
