سؤال

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

الكود الخاص بي يفعل هذا:

// the factory
class SomeFactoryImpl {
   Set<SomeClass> getSomeListOfObjects();
}

وفي مكان ما في الكود:

{ ...
    SomeFactory factory = new SomeFactoryImpl();
    Set<SomeClass> list = factory.getSomeListOfObjects();
}

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

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

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

فهل يمكن لمجتمع SO تقديم أمثلة يكون فيها إنشاء كائن Factory أفضل من استخدام طرق الإنشاء الثابتة؟

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

هل كانت مفيدة؟

المحلول

يُظهر استخدام مثيل المصنع الفوائد الحقيقية عند دمجه مع حقن التبعية.

لذلك في المثال الخاص بك، بدلا من:

{ ...
    SomeFactory factory = new SomeFactoryImpl();
    Set<SomeClass> list = factory.getSomeListOfObjects();
}

سيكون لديك:

public ThisClass(SomeFactory someFactory) {
    this.factory = someFactory;
}   

ثم في وقت لاحق...

{ ...
    Set<SomeClass> list = factory.getSomeListOfObjects();
}

بعض النقاط:

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

أعلم أن هذا لا يعالج سوى مجموعة فرعية من سؤالك ...

نصائح أخرى

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

وأيضًا إذا كان المصنع يعتمد على بعض معلومات السياق الديناميكي (اتصالات قاعدة البيانات، ...) فمن الأفضل في رأيي السماح لمثيل المصنع بالتعامل مع هذا الأمر.

أولًا، نسيت الهدف الرئيسي من نمط المصنع، فتحت كتاب عصابة الأربعة وجاء فيه:

"حدد واجهة لإنشاء كائن، ولكن دع الفئات الفرعية تقرر الفئة التي سيتم إنشاء مثيل لها.يتيح أسلوب المصنع للفئة تأجيل إنشاء مثيل للفئات الفرعية."

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

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

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

لهذا السبب أقوم بإنشاء مثيلات لكائنات المصنع

  1. فهو يسمح لي بإنشاء مصنع وتكوينه (لإنشاء عناصر واجهة مستخدم زرقاء مقابل إنشاء عناصر واجهة مستخدم زرقاء).عناصر واجهة المستخدم الحمراء وما إلى ذلك) ثم اجعلها متاحة لإنشاء عناصر واجهة المستخدم الزرقاء الخاصة بي، وعناصر واجهة المستخدم الحمراء عند الطلب.لاحظ أن هذا يختلف عن وجود RedWidgetFactory, BlueWidgetFactory.يكون التكوين متعامدًا مع نوع (أنواع) الكائنات التي يتم إنشاؤها
  2. فهو يقلل من مشكلات الترابط المحتملة التي قد تواجهها باستخدام مصنع واحد (يتم الوصول إليه عبر طريقة ثابتة) في جميع أنحاء نظامك.ربما يكون هذا دفاعيًا بعض الشيء، لكنني وجدت أن هذه عقلية جيدة (خاصة في الأنظمة الكبيرة).بالطبع يعتمد الأمر على كيفية إنشاء الكائنات الخاصة بك (على سبيل المثال.هل يقوم مصنعك بإنشاء المكونات الأساسية المشتركة)

IMO، الرمز الذي لديك يكون في الواقع عينة مناسبة من GoF مصنع مجردة النمط، حتى لو لم يكن استخدامه مثاليًا تمامًا.إذا كنت أتذكر بشكل صحيح، فإن كتاب GoF يصف العلاقة بين المصانع (SomeFactory، SomeFactoryImpl) والمنتجات (SomeClass) ولكنه يترك تفاصيل إنشاء المصانع مفتوحة.

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

  1. اطلب من فئة أخرى ("مدير المصنع" إذا جاز التعبير) تحديد تنفيذ المصنع الخاص بك بناءً على معلمة (على سبيل المثال، DriverManager في JDBC)، أو معلومات السياق الأخرى.
  2. استخدم نوعًا من إطار حقن التبعية.

إذا اخترت رقم 1، فأنا شخصيًا أحاول تصميمه وفقًا لـ JDBC، حيث:

  • Driver سيكون المصنع المجرد
  • Connections, Statements الخ هي المنتجات
  • DriverManager (غير محدد في كتاب GoF بشكل صريح) هي فئة الأداة المساعدة التي تحدد مصنعًا لك بناءً على عنوان URL الخاص بـ JDBC الذي تم تمريره

(في هذه الحالة، DriverManager يمضي قدمًا وينشئ المنتج لك أيضًا، إذا كنت تستخدم getConnection(...) الأساليب، كما يفعل معظم الناس.)

لربط الأمر بسؤالك، يمكن للمرء استخدام JDBC عن طريق الاتصال

new OracleDriver().connect(...)

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

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

آمل أن يكون هذا يجيب عن سؤالك.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top