هل من المقبول تمرير المعلمات إلى طريقة المصنع؟

StackOverflow https://stackoverflow.com/questions/615523

سؤال

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

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

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

class ApplicationBuilder {
  House build() {
    return new House(new Kitchen(
               new Sink(),
               new Dishwasher(),
               new Refrigerator())
           );
  }
}

ومع ذلك، ماذا يحدث إذا أردت أن يكون لكل منزل أقوم ببنائه اسم؟هل ما زلت أستخدم نمط المصنع إذا قمت بإعادة كتابة هذا الرمز على النحو التالي؟

class ApplicationBuilder {
  House build( const std::string & house_name) {
    return new House( house_name,
                      new Kitchen(new Sink(),
                                  new Dishwasher(),
                                  new Refrigerator())
                    );
  }
}

لاحظ أن استدعاء طريقة المصنع الخاص بي قد تغير من هذا:

ApplicationBuilder builder;
House * my_house = builder.build();

الى هذا:

ApplicationBuilder builder;
House * my_house = builder.build("Michaels-Treehouse");

بالمناسبة:أعتقد أن مفهوم فصل الكائنات عن منطق الأعمال أمر رائع، وأنا أحاول فقط معرفة كيف يمكنني تطبيقه على موقفي الخاص.ما يحيرني هو أن جميع الأمثلة التي رأيتها لنمط المصنع لا تمرر أي معلمات إلى وظيفة build().

لكي نكون واضحين:لا أعرف اسم المنزل حتى اللحظة التي سبقت أن أحتاج إلى إنشاء مثيل له.

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

المحلول

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

ولكن هناك سبب وجيه أن العديد من الدروس أو المواد الصغيرة تجنب يظهر المصانع التي توجيه المعلمات إلى الكائنات التي شيدت: هو عمليا من المستحيل إعادة توجيه عدد التعسفي من الحجج (حتى على حد عاقل مثل 6 الحجج). كل المعلمة التي لديها إلى الأمام لتكون مقبولة كما const T& وT& إذا كنت تريد أن تفعل ذلك عام.

لأمثلة أكثر تعقيدا، ومع ذلك، تحتاج إلى مجموعة متزايدة باطراد من الزائدة (لكل معلمة، وCONST ونسخة nonconst) و <لأ href = "http://blogs.msdn.com/vcblog/archive/ 2009/02/03 / rvalue المراجع-ج-0X-ميزات في VC10-الجزء 2.aspx "يختلط =" noreferrer "> الكمال الشحن غير ممكن على الإطلاق (بحيث يتم توجيه المؤقتة المتقبلة كما المؤقتات، على سبيل المثال). ل++ C ستاندرد المقبل يتم حل هذه المسألة:

class ApplicationBuilder {
  template<typename... T>
  House *build( T&&... t ) {
    return new House( std::forward<T>(t)...,
                      new Kitchen(new Sink(),
                                  new Dishwasher(),
                                  new Refrigerator())
                    );
  }
};

وبهذه الطريقة، يمكنك الاتصال

builder.build("Hello", 13);

وسيعود

new House("Hello", 13, new Kitchen(new Sink(...

وقراءة المقال ط مرتبطة أعلاه.

نصائح أخرى

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

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

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

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

طبعا، لم لا..!؟

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

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

وtypedef ولوكي :: SingletonHolder <وكي :: مصنع <المكونات والأمراض المنقولة جنسيا :: سلسلة، وكي :: Typelist >>> ComponentFactory؛

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

وComponentFactory :: مثيل () CREATEOBJECT ( "someStringAssociatedWithConcreteType"، anDataCollection، aGamePointer)؛.

لإنشاء كائنات، لتسجيل واحد فقط استخدام ComponentFactory :: مثيل (). التسجيل () ؛. هناك فصل كبير على التفاصيل في كتاب الحديثة تصميم C ++.

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