Dependency Injection Design Pattern

3zcsمنذ 8 سنوات

بسم الله الرحمن الرحيم

نكمل ما بدأنا به في شرح 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

كلمات دليلية:
4
إعجاب
14002
مشاهدات
0
مشاركة
3
متابع
متميز
محتوى رهيب

التعليقات (1)

يوسف سليمان:

شكرا علي مجهودك لنشر المعرفه

لايوجد لديك حساب في عالم البرمجة؟

تحب تنضم لعالم البرمجة؟ وتنشئ عالمك الخاص، تنشر المقالات، الدورات، تشارك المبرمجين وتساعد الآخرين، اشترك الآن بخطوات يسيرة !