كيفية القيام دليل DI مع الرسوم البيانية الكائن العميق والعديد من التبعيات بشكل صحيح
-
19-09-2019 - |
سؤال
أعتقد أن هذه الأسئلة قد سئلت في بعض أو الطريقة الأخرى ولكني لا أحصل عليها بعد.
نحن نقوم بمشروع GWT وقائد مشروعي غير مسموح باستخدام GIN / Guice كإطار عامل (مبرمجات جديدة لن يفهمها، جادل) لذلك أحاول أن أفعل DI يدويا.
الآن لدي مشكلة في الرسوم البيانية الكائن العميق. يشبه التسلسل الهرمي للكائن من واجهة المستخدم:
apppresenter-> dashboardpresenter-> gadgetpresenter-> gadgetconfigpresenter
The Gadgetconfigpresenter طريقة أسفل شجرة التسلسل الهرمي لها عدد قليل من التبعيات مثل العظام، وجهاز التوجيه، والفلتات، والآلات التوريزية، إلخ.
لذلك يحتوي GADGETPRESENTER الذي يقوم بإنشاء Gadgetconfigpresenter أيضا هذه التبعيات وهلم جرا، ما يصل إلى نقطة إدخال التطبيق التي تنشئ Apppresenter.
- هل هذه الطريقة دليل DI من المفترض أن تعمل؟
- لا يعني هذا أن أقوم بإنشاء جميع التبعيات في وقت التمهيد حتى لا أحتاج إليهم؟
- هل سيساعدني إطار العمل مثل الجن / الغيار هنا؟
المحلول
تكتب ذلك
gadgetpresenter الذي يخلق gadgetconfigpresenter [.
بدلا من إنشاء مباشرة GadgetConfigPresenter
الحالات، GadgetPresenter
ينبغي تأخذ التبعية على مصنع مجردة التي يمكن أن تخلق GadgetConfigPresenter
مثيلات لذلك. هذا يدفع التبعيات الداخلية GadgetConfigPresenter
إلى المصنع.
استخدام حقن منشئ على طول الطريق، الخاص بك رجل فقير دي يجب أن تبدو الأسلاك مثل هذا (الاعتذار عن بناء جملة C #):
var customerRepository = new CustomerRepository(/*...*/);
var projectRepository = new ProjectRepository(/*...*/);
var mandatorRepository = new MandatorRepository(/*...*/);
var gadgetConfigPresenterFactory =
new GadgetConfigPresenterFactory(
customerRepository,
projectRepository,
mandatorRepository);
var gadgetPresenter = new GadgetPresenter(gadgetConfigPresenterFactory);
var dashboardPresenter = new DashboardPresenter(gadgetPresenter);
var appPresenter = new AppPresenter(dashboardPresenter);
لاحظ كيف نحن كسر سلسلة التبعية في كثير من الأحيان، ضمان أن عدد التبعيات لكل مستهلك لا يصبح أبدا كبيرا جدا.
من حيث المبدأ، وهذا يعني أنه يجب عليك إنشاء جميع التبعيات في وقت التمهيد، ما لم تنفذ استراتيجية التحميل كسول.
مثل هذه الأشياء مثل إدارة العمر هي بالضبط نوع الشيء حيث يمكن أن تكون حاوية DI مفيدة بشكل كبير، ولكن من الممكن تماما كتابة تطبيق كامل من قبل بعد أنماط ومبادئ di.
الكل في الكل، ولكن، ما زلت أوصي بحاوية دي إذا كان ذلك ممكنا.
نصائح أخرى
يمكنك القيام DI باستخدام واجهات السياق. انها ليست صعبة، إلى الأمام على التوالي إلى حد ما.
واجهة السياق هي فئة تعرض كل الارتباطات من تكوين وحدة الغيار.
هذا مثال على ذلك حيث أفترض أن Apppresenter + DashboardPresEnter في حزمة واحدة وتحتاج إلى "سياق" واحد، في حين أن GadgetPresenter و Gadgetconfigpresenter في حزمة أخرى وتحتاج إلى "سياق" آخر. عدد السياقات، وكيفية التعامل معها هو ما يصل تماما إلى المستخدم.
/**
* The dependencies that need to be injected for package1
*/
public interface SomePackageContext {
GadgetPresenter getGadgetPresenter();
GadgetConfigPresenter getGadgetConfigPresenter();
}
/**
* The dependencies that need to be injected for package2
*/
public interface OtherPackageContext {
// These methods can take arguments..
AppPresenter getAppPresenter(Args..);
DashboardPresenter getDashboardPresenter(Args..);
}
/**
* All of the DI needed in our project.
*
* <p>We don't need the two interfaces above, we can put
* everything in this interface if we have a small
* project where layering is not a big issue.
*/
public interface PresenterContext
extends SomePackageContext, OtherPackageContext {
}
public class MockPresenterContext implements PresenterContext {
...
}
public class RealPresenterContext implements PresenterContext {
// This is similar to bind(...) in guice
public AppPresenter getAppPresenter(Args..) {
return new AppPresenter(this, otherargs...);
}
public DashboardPresenter getDashboardPresenter(Args..) {
return new DashboardPresenter(this, otherargs...);
}
public GadgetPresenter getGadgetPresenter() {
return new GadgetPresenter(this);
}
public GadgetConfigPresenter getGadgetConfigPresenter() {
return new GadgetConfigPresenter();
}
}
public class DashboardPresenter {
// @Inject
private final GadgetPresenter gadgetPresenter;
/*
* We inject everything using the SomePackageContext.
*/
public DashboardPresenter(SomePackageContext ctxt) {
this.gadgetPresenter = ctxt.getGadgetPresenter();
}
}