المصنع (البرمجة الموجهة للكائنات)

في البرمجة كائنية التوجه ، يُعرَّف المصنع بأنه كائن يُستخدم لإنشاء كائنات أخرى ؛ وهو، بشكل رسمي، دالة أو أسلوب يُعيد كائنات من نموذج أولي أو فئة متغيرة [ 1 ] من استدعاء أسلوب ما، يُفترض أنه جديد . [ أ ] وبشكل أعم، يُمكن الإشارة إلى روتين فرعي يُعيد كائنًا جديدًا باسم مصنع ، كما في أسلوب المصنع أو دالة المصنع . يُعد نمط المصنع أساسًا لعدد من أنماط تصميم البرمجيات ذات الصلة .
الدافع
في البرمجة القائمة على الأصناف ، يُمثل المصنع تجريدًا لدالة البناء الخاصة بصنف ما، بينما في البرمجة القائمة على النماذج الأولية، يُمثل المصنع تجريدًا لكائن نموذج أولي. دالة البناء ملموسة لأنها تُنشئ كائنات كنسخ من صنف واحد، ومن خلال عملية محددة (إنشاء نسخة من الصنف)، بينما يُمكن للمصنع إنشاء كائنات عن طريق إنشاء نسخ من أصناف مختلفة، أو باستخدام وسائل تخصيص أخرى، مثل مجمع الكائنات . كائن النموذج الأولي ملموس لأنه يُستخدم لإنشاء كائنات عن طريق استنساخه ، بينما يُمكن للمصنع إنشاء كائنات عن طريق استنساخ نماذج أولية مختلفة، أو باستخدام وسائل تخصيص أخرى.
يمكن تنفيذ المصنع بطرقٍ مختلفة. في أغلب الأحيان، يُنفذ كدالة، وفي هذه الحالة يُسمى دالة مصنع . أحيانًا يُنفذ كدالة، وفي هذه الحالة يُسمى دالة مصنع . في بعض اللغات، تُعتبر الدوال البانية مصانع. مع ذلك، في معظم اللغات، لا تُعتبر كذلك، ويتم استدعاء الدوال البانية بطريقةٍ خاصة باللغة، مثل استخدام الكلمة المفتاحية `constructor` new، بينما لا يتمتع المصنع بوضعٍ خاص ويتم استدعاؤه عبر استدعاء دالة أو دالة عادية. في هذه اللغات، يُعد المصنع تجريدًا للدالة البانية، ولكنه ليس تعميمًا دقيقًا، لأن الدوال البانية ليست مصانع.
مصطلحات
تختلف المصطلحات حول ما إذا كان مفهوم المصنع نمط تصميم أم لا؛ ففي أنماط التصميم ، لا يوجد نمط مصنع بالمعنى المتعارف عليه، بل نمطان ( نمط طريقة المصنع ونمط المصنع المجرد ) يستخدمان المصانع. تشير بعض المصادر إلى المفهوم بنمط المصنع ، [ 2 ] [ 3 ] بينما تعتبره مصادر أخرى مصطلحًا برمجيًا ، [ 4 ] وتحصر مصطلح نمط المصنع أو أنماط المصانع في الأنماط الأكثر تعقيدًا التي تستخدم المصانع، وغالبًا ما يكون نمط طريقة المصنع؛ في هذا السياق، قد يُشار إلى مفهوم المصنع بمصنع بسيط . [ 4 ] في سياقات أخرى، وخاصة لغة بايثون ، يُستخدم مصطلح المصنع ، كما هو الحال في هذه المقالة. [ 5 ] وبشكل أوسع، يمكن تطبيق مصطلح المصنع ليس فقط على كائن يُعيد كائنات من استدعاء طريقة ما، بل على روتين فرعي يُعيد كائنات، كما في دالة المصنع (حتى لو لم تكن الدوال كائنات) أو طريقة المصنع . [ 6 ] لأنه في العديد من اللغات يتم استدعاء المصانع عن طريق استدعاء طريقة، فإن المفهوم العام للمصنع غالبًا ما يتم الخلط بينه وبين نمط تصميم طريقة المصنع المحدد .
يستخدم
توفر البرمجة الكائنية التوجه تعدد الأشكال في استخدام الكائنات من خلال إرسال الدوال ، أو ما يُعرف رسميًا بتعدد الأشكال الفرعي عبر إرسال واحد يُحدد بنوع الكائن الذي تُستدعى عليه الدالة. مع ذلك، لا ينطبق هذا على الدوال البانية، لأنها تُنشئ كائنًا من نوع معين، بدلًا من استخدام كائن موجود. بعبارة أخرى ، عند استدعاء دالة بانية، لا يوجد كائن بعد لإرسال الدالة إليه .
يُتيح استخدام المصانع بدلاً من المُنشئات أو النماذج الأولية استخدام تعدد الأشكال لإنشاء الكائنات، وليس فقط لاستخدامها. وبالتحديد، يوفر استخدام المصانع تغليفًا ، مما يعني أن الكود غير مرتبط بفئات أو كائنات مُحددة، وبالتالي يُمكن تغيير أو إعادة هيكلة التسلسل الهرمي للفئات أو النماذج الأولية دون الحاجة إلى تغيير الكود الذي يستخدمها - فهي تُجرّد الكود من التسلسل الهرمي للفئات أو النماذج الأولية.
من الناحية الفنية، في اللغات التي تعمم فيها المصانع المنشئات، يمكن عادةً استخدام المصانع في أي مكان يمكن فيه استخدام المنشئات، [ ج ] مما يعني أن الواجهات التي تقبل منشئًا يمكنها أيضًا بشكل عام قبول مصنع - عادةً ما يحتاج المرء فقط إلى شيء يقوم بإنشاء كائن، بدلاً من الحاجة إلى تحديد فئة وإنشاء مثيل.
على سبيل المثال، في لغة بايثون، تحتوي collections.defaultdictالفئة [ 7 ] على دالة إنشاء تُنشئ كائنًا من النوع defaultdict[ d ]، وتُنتج قيمه الافتراضية باستدعاء دالة مصنع. تُمرر دالة المصنع كوسيط إلى دالة الإنشاء، ويمكن أن تكون دالة إنشاء، أو أي شيء يتصرف كدالة إنشاء - أي كائن قابل للاستدعاء يُعيد كائنًا، أي دالة مصنع. على سبيل المثال، استخدام listدالة الإنشاء للقوائم:
from collections import defaultdict# collections.defaultdict([default_factory[, ...]]) d : defaultdict [ str , list [ int ]] = defaultdict ( list )إنشاء الكائنات
تُستخدم كائنات المصنع في الحالات التي يكون فيها الحصول على كائن من نوع معين عمليةً أكثر تعقيدًا من مجرد إنشاء كائن جديد، لا سيما إذا كانت هناك حاجة إلى تخصيص أو تهيئة معقدة. تتضمن بعض العمليات المطلوبة لإنشاء كائن ما تحديد نوع الكائن المراد إنشاؤه، وإدارة دورة حياته، وإدارة عمليات الإنشاء والإزالة الخاصة به. قد يقرر كائن المصنع إنشاء فئة الكائن (إن وجدت) ديناميكيًا، أو إعادته من مجمع كائنات ، أو إجراء تهيئة معقدة عليه، أو غير ذلك. وبالمثل، وفقًا لهذا التعريف، يُعدّ الكائن الأحادي المُنفَّذ بنمط الكائن الأحادي مصنعًا رسميًا - فهو يُعيد كائنًا، لكنه لا يُنشئ كائنات جديدة تتجاوز مثيلًا واحدًا.
على سبيل المثال، في لغة C++ ، تحتوي فئات المؤشر الذكيstd::unique_ptr<T> على std::shared_ptr<T>وظائف المصنع std::make_unique<T>()و std::make_shared<T>()، والتي تقوم بتمرير المعلمات إلى عملية الإنشاء.
أمثلة
أبسط مثال على المصنع هو دالة المصنع البسيطة، التي تستدعي مُنشئًا وتُعيد النتيجة. في بايثون ، يمكن تنفيذ دالة المصنع fالتي تُنشئ نسخة من فئة ما على النحو التالي:A
def f () -> A : return A ()دالة المصنع البسيطة التي تُنفذ نمط التصميم الأحادي هي:
def f () -> A : if f . obj is None : f . obj = A () return f . objf.obj = Noneسيؤدي هذا إلى إنشاء كائن عند استدعائه لأول مرة، وسيعيد دائمًا نفس الكائن بعد ذلك.
بناء الجملة
يمكن استدعاء المصانع بطرق متنوعة، وأكثرها شيوعًا استدعاء دالة ( دالة مصنع )، وأحيانًا استدعاؤها كدالة إذا كان المصنع كائنًا قابلاً للاستدعاء ( دالة مصنع ). في بعض اللغات، تتطابق صيغة المُنشئات والمصانع، بينما في لغات أخرى، تكون صيغة المُنشئات خاصة. في اللغات التي تتطابق فيها صيغة المُنشئات والمصانع، مثل بايثون، وبيرل، وروبي، وأوبجكت باسكال، وإف شارب ، يمكن استبدال المُنشئات بالمصانع بسلاسة . أما في اللغات التي تختلف فيها الصيغة، فيجب التمييز بينهما في الواجهات، ويتطلب التبديل بين المُنشئات والمصانع تغيير الاستدعاءات.
علم الدلالة
في اللغات التي تُخصص فيها الكائنات ديناميكيًا ، مثل جافا وبايثون، تُعتبر المصانع مكافئة دلاليًا للمنشئات. أما في لغات مثل C++ التي تسمح بتخصيص بعض الكائنات بشكل ثابت ، فإن المصانع تختلف عن المنشئات للفئات المُخصصة بشكل ثابت، إذ يُمكن تحديد تخصيص الذاكرة للمنشئات في وقت الترجمة ، بينما يجب تحديد تخصيص القيم المُعادة من المصانع في وقت التشغيل. إذا كان من الممكن تمرير مُنشئ كوسيط لدالة، فيجب استدعاء المُنشئ وتخصيص القيمة المُعادة ديناميكيًا في وقت التشغيل، وبالتالي يكون لهما دلالات مشابهة أو مطابقة لاستدعاء مصنع.
أنماط التصميم
تُستخدم المصانع في أنماط تصميم متنوعة ، وتحديدًا في أنماط الإنشاء مثل نمط مكتبة الكائنات . وقد طُوّرت وصفات محددة لتطبيقها في العديد من لغات البرمجة. على سبيل المثال، تُعدّ العديد من أنماط GoF ، مثل نمط طريقة المصنع ، ونمط البناء ، وحتى نمط Singleton ، تطبيقات لهذا المفهوم. أما نمط المصنع المجرد فهو طريقة لإنشاء مجموعات من المصانع.
في بعض أنماط التصميم، يحتوي كائن المصنع على دالة لكل نوع من أنواع الكائنات التي يمكنه إنشاؤها. تقبل هذه الدوال، اختيارياً، معلمات تحدد كيفية إنشاء الكائن، ثم تُعيد الكائن الذي تم إنشاؤه.
التطبيقات
تُعدّ كائنات المصنع شائعة في مجموعات أدوات الأدوات البرمجية وأطر العمل البرمجية ، حيث يحتاج كود المكتبة إلى إنشاء كائنات من أنواع يمكن للتطبيقات التي تستخدم إطار العمل أن ترث منها. كما تُستخدم أيضًا في تطوير البرمجيات الموجه بالاختبار للسماح بوضع الفئات تحت الاختبار. [ 8 ]
تُحدد المصانع النوع الملموس للكائن المراد إنشاؤه، وفيها يتم إنشاء الكائن. ولأن المصنع لا يُعيد سوى واجهة مجردة للكائن، فإن كود العميل لا يعرف، ولا يتحمل عبء، النوع الملموس للكائن الذي تم إنشاؤه للتو. مع ذلك، فإن نوع الكائن الملموس معروف للمصنع المجرد. وهذا يعني تحديدًا ما يلي:
- لا يمتلك كود العميل أي معرفة بنوع البيانات الملموس ، ولا يحتاج إلى تضمين أي ملفات رأسية أو تعريفات فئات متعلقة بهذا النوع. يتعامل كود العميل فقط مع النوع المجرد. صحيح أن المصنع يُنشئ كائنات من نوع ملموس، لكن كود العميل لا يصل إلى هذه الكائنات إلا من خلال واجهتها المجردة .
- تتم إضافة أنواع بيانات جديدة عن طريق تعديل كود العميل لاستخدام مصنع مختلف، وهو تعديل لا يتجاوز عادةً سطرًا واحدًا في ملف واحد. يُعدّ هذا أسهل بكثير من تعديل كود العميل لإنشاء نوع جديد، الأمر الذي يتطلب تغيير كل موضع في الكود حيث يتم إنشاء كائن جديد.
قابلية التطبيق
يمكن استخدام المصانع عندما:
- إن إنشاء كائن يجعل إعادة استخدامه مستحيلة دون تكرار كبير للتعليمات البرمجية.
- يتطلب إنشاء كائن الوصول إلى معلومات أو موارد لا ينبغي أن تكون موجودة داخل فئة الإنشاء.
- يجب أن تكون إدارة دورة حياة الكائنات المُنشأة مركزية لضمان سلوك متسق داخل التطبيق.
تُعد المصانع، وتحديداً أساليب المصانع، شائعة في مجموعات أدوات الأدوات البرمجية وأطر البرامج ، حيث يحتاج كود المكتبة إلى إنشاء كائنات من أنواع يمكن أن يتم تصنيفها فرعياً بواسطة التطبيقات التي تستخدم إطار العمل.
غالباً ما تتطلب التسلسلات الهرمية المتوازية للفئات أن تكون الكائنات من تسلسل هرمي واحد قادرة على إنشاء كائنات مناسبة من تسلسل هرمي آخر.
تُستخدم أساليب المصنع في تطوير البرمجيات الموجه بالاختبارات لتمكين اختبار الفئات. [ 9 ]Foo إذا أنشأت فئةٌ ما كائنًا آخر Dangerousلا يمكن اختباره آليًا (ربما يتواصل مع قاعدة بيانات إنتاجية غير متاحة دائمًا)، فإن إنشاء Dangerousالكائنات يُوضع في أسلوب المصنع الافتراضيcreateDangerous في الفئة Foo. ولأغراض الاختبار، تُنشأ TestFooفئة فرعية من الفئة ، مع إعادة تعريف أسلوب المصنع الافتراضي لإنشاء وإرجاع كائن وهمي . ثم تستخدم اختبارات الوحدة هذا الكائن لاختبار وظائفه دون التسبب في الآثار الجانبية لاستخدام كائن حقيقي.FoocreateDangerousFakeDangerousTestFooFooDangerous
المزايا والخيارات
إلى جانب استخدامها في أنماط التصميم، تتمتع المصانع، وخاصة أساليب المصانع، بفوائد وتنوعات مختلفة.
أسماء وصفية
تتميز دوال المصنع باسمٍ فريد. في العديد من لغات البرمجة كائنية التوجه، يجب أن تحمل الدوال البانية نفس اسم الصنف الذي تنتمي إليه، مما قد يؤدي إلى غموض إذا وُجدت أكثر من طريقة لإنشاء كائن (انظر التحميل الزائد ). لا تخضع دوال المصنع لهذا القيد، ويمكن أن تحمل أسماءً وصفية؛ وتُعرف أحيانًا بالدوال البانية البديلة . على سبيل المثال، عند إنشاء أعداد مركبة من عددين حقيقيين، يمكن تفسير الأعداد الحقيقية على أنها إحداثيات ديكارتية أو قطبية، ولكن باستخدام دوال المصنع، يكون المعنى واضحًا، كما هو موضح في المثال التالي بلغة C# .
namespace Wikipedia.Examples ;باستخدام النظام ؛public class Complex { public double Real { get ; set ; } public double Imaginary { get ; set ; }private Complex ( double real , double imaginary ) { this . Real = real ; this . Imaginary = imaginary ; }public static Complex FromCartesian ( double real , double imaginary ) { return new Complex ( real , imaginary ); }public static Complex FromPolar ( double modulus , double angle ) { return new Complex ( modulus * Math . Cos ( angle ), modulus * Math . Sin ( angle )); } }الناتج المركب = Complex.FromPolar ( 1 , Math.PI ) ;عند استخدام أساليب المصنع لإزالة الغموض على هذا النحو، غالبًا ما يتم جعل المنشئات الأولية خاصة لإجبار العملاء على استخدام أساليب المصنع.
التغليف
تُغلف أساليب المصنع عملية إنشاء الكائنات. قد يكون هذا مفيدًا إذا كانت عملية الإنشاء معقدة للغاية؛ على سبيل المثال، إذا كانت تعتمد على إعدادات في ملفات التكوين أو على مدخلات المستخدم.
لنأخذ على سبيل المثال برنامجًا يقرأ ملفات الصور . يدعم البرنامج تنسيقات صور مختلفة، ممثلة بفئة قارئ لكل تنسيق.
في كل مرة يقرأ فيها البرنامج صورة، يحتاج إلى إنشاء قارئ من النوع المناسب بناءً على بعض المعلومات الموجودة في الملف. يمكن تغليف هذه العملية المنطقية في دالة مصنع. يُشار إلى هذا النهج أيضًا باسم "المصنع البسيط".
جافا
package org.wikipedia.imageio ;استيراد javax.imageio.ImageReader ؛public class ImageReaderFactory { public static ImageReader createImageReader ( ImageInputStreamProcessor iisp ) { if ( iisp . isGIF ()) { return new GifReader ( iisp . getInputStream ()); } else if ( iisp . isJPEG ()) { return new JpegReader ( iisp . getInputStream ()); } throw new IllegalArgumentException ( "نوع الصورة غير معروف." ); } }PHP
class Factory { public static function build ( string $type ) : FormatInterface { $class = "Format" . $type ; return new $class ; } }واجهة FormatInterface {}class FormatString implements FormatInterface {} class FormatNumber implements FormatInterface {}حاول { $string = Factory :: build ( "String" ); } catch ( Error $e ) { echo $e- > getMessage (); }حاول { $number = Factory :: build ( "Number" ); } catch ( Error $e ) { echo $e- > getMessage (); }الحدود
هناك ثلاثة قيود مرتبطة باستخدام أسلوب المصنع. الأول يتعلق بإعادة هيكلة الكود الموجود؛ أما الآخران فيتعلقان بتوسيع فئة.
- يتمثل القيد الأول في أن إعادة هيكلة فئة موجودة لاستخدام المصانع يؤدي إلى تعطيل العملاء الحاليين. على سبيل المثال، إذا كانت الفئة Complex فئة قياسية، فقد يكون لها العديد من العملاء الذين لديهم كود مشابه لما يلي: عند إدراك الحاجة إلى مصنعين مختلفين، يتم تغيير الفئة (إلى الكود الموضح سابقًا ). ولكن نظرًا لأن المُنشئ أصبح خاصًا، فإن كود العميل الحالي لم يعد يُترجم.
Complexc=newComplex(-1,0); - أما القيد الثاني فهو أنه بما أن النمط يعتمد على استخدام مُنشئ خاص، فلا يمكن توسيع الفئة. يجب على أي فئة فرعية استدعاء المُنشئ الموروث، ولكن لا يمكن القيام بذلك إذا كان هذا المُنشئ خاصًا.
- أما القيد الثالث فهو أنه في حال توسيع الصنف (مثلاً، بجعل المُنشئ محميًا - وهذا محفوف بالمخاطر ولكنه ممكن)، يجب على الصنف الفرعي توفير إعادة تنفيذ خاصة به لجميع دوال المصنع بنفس التوقيعات تمامًا. على سبيل المثال، إذا كان الصنف
StrangeComplexيمتد من الصنف الأصليComplex، فإنه ما لمStrangeComplexيُوفر الصنف الفرعي نسخته الخاصة من جميع دوال المصنع، فإن الاستدعاء سيُنتج نسخة من الصنف الأصلي بدلاً من النسخة المتوقعة من الصنف الفرعي. يمكن لبعض لغات البرمجة تجنب هذه المشكلة باستخدام ميزات البرمجة الانعكاسية (الانعكاس).StrangeComplex.FromPolar(1,Math.Pi);Complex
يمكن التخفيف من حدة المشاكل الثلاث عن طريق تغيير لغة البرمجة الأساسية لجعل المصانع أعضاءً من الدرجة الأولى في الفئة (انظر أيضًا الفئة الافتراضية ). [ 10 ]
ملحوظات
- ↑ من ناحية الواجهة، يمكن استخدام أي كائن يُرجع كائنًا كمصنع، ولكن من الناحية الدلالية، يُرجع المصنع إما كائنًا تم إنشاؤه حديثًا، مثل مثيل فئة أو نسخة من نموذج أولي، أو كائنًا يبدو جديدًا، مثل كائن تمت إعادة تهيئته من مجموعة كائنات.
- في اللغات التي تُعتبر فيها الدوال البانية أساليبًا على كائن من فئة ( أساليب الفئة )، يوجد كائن موجود بالفعل، وتُعدّ الدوال البانية حالات خاصة من أساليب المصنع، حيث يُعتبر الإنشاء متعدد الأشكال حالة خاصة من إرسال الأساليب متعدد الأشكال. أما في اللغات الأخرى، فيوجد تمييز واضح بين الدوال البانية والأساليب.
- ↑ يمكن استخدام المُنشئات في أي مكان يمكن استخدام المصانع فيه، لأنها حالة خاصة.
- ↑ هذه الفئة هي فئة فرعية من
dict، وهي تطبيق بايثون المدمج للخرائط أو القواميس. - ↑ في حالة حذفالكلمة المفتاحية الاختيارية
new
مراجع
- ↑ غاما، إريك (1994). أنماط التصميم . أديسون-ويسلي. ص 18-19 . ISBN 9780321700698.
- ↑ نمط المصنع ، OODesign.com
- ↑ نمط المصنع ، ويكي ويكي ويب
- الفصل الرابع : نمط المصنع: الخبز باستخدام البرمجة الكائنية (مؤرشف بتاريخ 11 مارس 2017 في أرشيف الإنترنت ) تعريف المصنع البسيط ( مؤرشف بتاريخ 19 فبراير 2014 في أرشيف الإنترنت)
- ↑ 30.8 الأصناف هي كائنات: مصانع الكائنات العامة ، تعلم بايثون، بقلم مارك لوتز، الطبعة الرابعة، دار نشر أورايلي ميديا، رقم ISBN 978-0-596-15806-4
- ↑ طريقة المصنع ، ويكي ويكي ويب
- ↑ كائنات القاموس الافتراضي
- ↑ فيذرز، مايكل (أكتوبر 2004). العمل بفعالية مع البرامج القديمة . أبر سادل ريفر، نيو جيرسي: برنتيس هول بروفيشنال تكنيكال ريفرنس. ISBN 978-0-13-117705-5.
- ↑ فيذرز، مايكل (أكتوبر 2004). العمل بفعالية مع البرامج القديمة . أبر سادل ريفر، نيوجيرسي: برنتيس هول بروفيشنال تكنيكال ريفرنس. ISBN 978-0-13-117705-5.
- ↑ أجربو، إيلين؛ كورنيلز، أينو (1998). "كيفية الحفاظ على مزايا أنماط التصميم". مؤتمر حول أنظمة ولغات وتطبيقات البرمجة كائنية التوجه . فانكوفر، كولومبيا البريطانية، كندا: ACM: 134-143 . ISBN 1-58113-005-8.
- إريك، فريمان؛ روبسون، إليزابيث؛ بيتس، بيرت؛ سييرا، كاثي (2009) [2004]. أنماط التصميم من Head First . Head First . أورايلي. ISBN 978-0-596-55656-3.
- البرمجة الكائنية التوجه
- مقارنات لغات البرمجة
