Dependency Injection Design Pattern
بسم الله الرحمن الرحيم
نكمل ما بدأنا به في شرح design pattern الأكثر استخداما في بيئة Android
اليوم بإذن الله سيكون حديثنا عن مفهوم Dependency Injection.
تعريف wikipedia
اقتباسهو design pattern يقوم بعمل implementation لمبدأ Inversion of Control لحل أو تحليل الاعتمادية.
فما هو Inversion of Control ؟ التعريف من wikipedia أيضا
اقتباسهو أن تسمح ل code أخر بأن يقوم بالأستدعاء بدلا من أن تقوم به.
قد تكون عملية الترجمة غير مجدية أو أن التعريفات ليست واضحة عموما بإذن الله سنفصل الموضوع تفصيلا بسيطاً يجعله واضحا بإذن الله.
ببساطة مفهوما Dependency Injection و Inversion of Control (IoC) بدون الخوض في التفاصيل تعنى بحذف dependencies من code
ماذا نعني ب dependencies (الاعتمادية) ؟
خذ هذا المثال
public class MSWord
{
private ErrorCorrection corrector;
public MSWord()
{
this.corrector = new ErrorCorrection();
}
}
نلاحظ أنه لكي أقوم بإنشاء Object من class MSWrod فأنا مضطر لإنشاء Object من class ErrorCorrection ونقطة الاعتمادية هنا هي إنشاء Object
لكي تقوم بتنفيذ Dependency Injection لابد أن تعمل Inject (حقن) object بحيث يأتي إلى class ك parameter مبني, فتتم عملية الإسناد فقط
بالمثال يتضح المقال, فهذه مثال ننفذ فيه Dependency Injection على نفس code السابق
public class MSWord
{
private ErrorCorrection corrector;
public MSWord(ErrorCorrection corrector)
{
this.corrector = corrector;
}
}
ففي Main أو مكان تنفيذ code ستقوم بالتالي
public static void main(String[] args) {
ErrorCorrection corrector = new ErrorCorrection()
MSWord word = new MSWord(corrector);
}
جميل جدا, الأمر نفسه بتمرير dependencies ك parameter سواء كان في constructor أو method, يأتي السؤال الأهم لماذا أستخدم هذا pattern ؟
لنفترض أن لدينا class A ولديه subclass B ويحتاج object من class C
public class C {
String s ;
C(String s){
this.s = s ;
}
}
public class A {
private C c ;
A(String s){
this.c = new C(s);
}
}
public class B extends A{
B(String s){
super(s);
}
}
جميل, في حال تم تغيير constructor في class C فأنت مضطر لتغيير constructor في class A وجميع من يرث منه, فلو قلنا فرضاً أننا قررنا إضافة Strimg أخر لدى C
public class C {
String s ,s1;
C(String s ,String s1 ){
this.s = s ;
this.s1 = s1 ;
}
}
public class A {
private C c ;
A(String s,String s1){
this.c = new C(s,s1);
}
}
public class B extends A{
B(String s,String s1){
super(s,s1);
}
}
فكما ترى اضطررنا لتغيير جميع classes نظرا لأننا غيرنا في class يعتمدون عليه, لكن ماذا لو طبقنا Dependency Injection على هؤلاء classes
public class C {
String s ;
C(String s){
this.s = s ;
}
}
public class A {
private C c ;
A(C c){
this.c = c ;
}
}
public class B extends A{
B(C c){
super(c);
}
}
لنغير في C و constructor الخاص بها ونرى ماذا يحدث.
public class C {
String s ,s1;
C(String s,String s1){
this.s = s ;
this.s1 = s1 ;
}
}
public class A {
private C c ;
A(C c){
this.c = c ;
}
}
public class B extends A{
B(C c){
super(c);
}
}
نلاحظ الفائدة Dependency Injection حيث أن التغيير تم في مكان واحد فقط.
من فوائد Dependency Injection
له فوائد جدا كثيرة ستلاحظها أثناء الكتابة أو حين تقرأ عنه ومنها
- قابلية التعديل - maintainability
- قابلية الاختبار - testability
- قابلية الاستفادة من نفس code عوضاً عن إعادة كتابته - reusability
- بالإضافة إلى أنه يقلل من coupling في code
للاستزادة هنا بعض المراجع التي قرأت منها وفيها الكثير من المعلومات التي فضلت عدم إيرادها لجعل الموضوع أكثر بساطة
https://en.wikipedia.org/wiki/Dependency_injection
http://frogermcs.github.io/dependency-injection-with-dagger-2-introdution-to-di/
http://stackoverflow.com/questions/3058/what-is-inversion-of-control
لايوجد لديك حساب في عالم البرمجة؟
تحب تنضم لعالم البرمجة؟ وتنشئ عالمك الخاص، تنشر المقالات، الدورات، تشارك المبرمجين وتساعد الآخرين، اشترك الآن بخطوات يسيرة !