حقن التبعية  في هندسة البرمجيات، يعد حقن التبعية تقنية يتلقى فيها كائن كائنات أخرى يعتمد عليها. تسمى هذه الكائنات الأخرى التبعيات.  في العلاقة النموذجية «باستخدام» يسمى الكائن المتلقي عميل ويسمى الكائن الذي تم تمريره (أي تم حقنه) خدمة . يمكن أن يكون الكود الذي ينقل الخدمة إلى العميل أنواعًا كثيرة ويسمى الحاقن. بدلاً من تحديد العميل للخدمة التي سيستخدمها، يخبر الحاقن العميل بالخدمة التي سيستخدمها. تشير «الحقن» إلى تمرير التبعية (خدمة) إلى الكائن (العميل) الذي قد يستخدمها.  الخدمة تصبح جزءاً من حالة العميل. يعد تمرير الخدمة إلى العميل، بدلاً من السماح للعميل ببناء الخدمة أو العثور عليها، شرطاً أساسياً للنمط.  النية من حقن التبعية هو تحقيق فصل الاهتمامات الخاصة بالبناء واستخدام الكائنات. يمكن أن يؤدي ذلك إلى زيادة إمكانية القراءة وإعادة استخدام الكود.  حقن التبعية هو شكل من أشكال التقنية الأوسع لعكس التحكم. لا يجب على العميل الذي يريد استدعاء بعض الخدمات معرفة كيفية إنشاء هذه الخدمات. بدلاً من ذلك، يفوض العميل مسؤولية توفير خدماته للكود الخارجي (الحاقن). لا يُسمح للعميل باستدعاء كود الحاقن ؛ الحاقن هو الذي يبني الخدمات. ثم يقوم الحاقن بحقن (تمرير) الخدمات في العميل التي قد تكون موجودة بالفعل أو قد يتم بناؤها بواسطة الحاقن. ثم يستخدم العميل الخدمات. هذا يعني أن العميل لا يحتاج إلى معرفة الحاقن، وكيفية إنشاء الخدمات، أو حتى الخدمات الفعلية التي يستخدمها. يحتاج العميل فقط إلى معرفة الواجهات الجوهرية للخدمات لأن هذه تحدد كيفية استخدام العميل للخدمات. وهذا يفصل مسؤولية «الاستخدام» عن مسؤولية «البناء» .  حقن التبعية يحل مشاكل مثل:  إنشاء كائنات مباشرة داخل الصنف أمر غير مرن لأنه يلزم الصنف بكائنات معينة ويجعل من المستحيل تغيير التمثيل الفوري بشكل مستقل عن الصنف (دون الحاجة إلى تغيير). يوقف الصنف عن إمكانية إعادة استخدامه.  إذا كانت هناك حاجة إلى كائنات أخرى، ويجعل من الصعب اختبار الصنف لأنه لا يمكن استبدال الكائنات الحقيقية بكائنات وهمية.  لم يعد الصنف مسؤول عن إنشاء الكائنات التي يتطلبها، ولا يتعين عليه تفويض إنشاء مثيل لكائن مصنع كما هو الحال في نمط تصميم. انظر أيضًا صنف UML ومخطط التسلسل أدناه.  حقن التبعية يفصل إنشاء تبعيات العميل عن سلوك العميل، والذي يسمح لتصاميم البرنامج أن تكون مقترنة بشكل متساهل ومتابعة انعكاس التبعية ومبادئ المسؤولية الواحدة. يتناقض بشكل مباشر مع نمط محدد مواقع الخدمة، والذي يسمح للعملاء بمعرفة النظام الذي يستخدمونه للعثور على التبعيات. الحقن، الوحدة الأساسية لحقن التبعية، ليست آلية جديدة أو مخصصة. يعمل بنفس الطريقة التي يعمل بها «تمرير المعلمة».  بالإشارة إلى «تمرير المعلمة» حيث أن الحقن يحمل ضمناً إضافياً أنه يتم القيام به لعزل العميل عن التفاصيل.  إن الحقن يتعلق أيضًا بما يتحكم في المرور (وليس العميل) مطلقًا وهو مستقل عن كيفية تحقيق التمرير، سواء عن طريق تمرير مرجع أو قيمة يشمل حقن التبعية أربعة أدوار: كمثال:  أي كائن يمكن استخدامه يمكن اعتباره خدمة. يمكن اعتبار أي كائن يستخدم كائنات أخرى عميلاً . "لا علاقة للأسماء بماهية الكائنات وكل شيء يتعلق بالدور الذي تلعبه الكائنات في أي حقن".  الواجهات هي الأنواع التي يتوقع العميل تبعياتها. المشكلة هي ما يجعلها متاحة. قد تكون بالفعل أنواع من الواجهة يتم تنفيذها بواسطة الخدمات ولكن قد تكون أيضًا أصناف مجردة أو حتى الخدمات نفسها على الرغم من أن هذا الأخير قد ينتهك DIP ويضحي بفك الارتباط الديناميكي الذي يتيح الاختبار. يتطلب فقط ألا يعرف العميل هويته وبالتالي لا يتعامل معه على أنه ملموس، على سبيل المثال من خلال إنشائها أو توسيعها.  يجب ألا يكون لدى العميل معرفة ملموسة بالتنفيذ المحدد لتبعياته. يجب أن يعرف فقط اسم الواجهة وواجهة برمجة التطبيقات . ونتيجة لذلك، لن يحتاج العميل إلى التغيير حتى إذا تغير ما وراء الواجهة. ومع ذلك، إذا تمت إعادة هيكلة الواجهة من صنف إلى نوع واجهة (أو العكس) فسيحتاج العميل إلى إعادة التجميع هذا مهم إذا تم نشر العميل والخدمات بشكل منفصل. هذا الاقتران المؤسف هو واحد لا يمكن حله بالتبعية. يقدم الحاقن الخدمات إلى العميل. في كثير من الأحيان، يقوم أيضًا بإنشاء العميل. قد يربط الحاقن معًا رسمًا بيانيًا معقدًا جدًا للكائن عن طريق معاملة كائن مثل العميل وبعد ذلك كخدمة لعميل آخر. قد يكون الحاقن. في الواقع العديد من الكائنات تعمل معًا ولكن قد لا يكون العميل. قد تتم الإشارة إلى الحاقن بأسماء أخرى مثل: المجمع، الموفر، الحاوية، المصنع، البناء، الربيع، كود البناء، أو الرئيسي.  يمكن تطبيق حقن التبعية كنظام، واحد يطلب من جميع الكائنات صنف البناء والسلوك. يمكن أن يؤدي الاعتماد على إطار عمل حقن التبعية بالقيام بالإنشاء إلى حظر استخدام الكلمة المفتاحية "new"، أو بشكل أقل صرامة، السماح بالبناء المباشر لعناصر القيمة فقط.  يعد عكس التحكم (IoC) أكثر عمومية من حقن التبعية. ببساطة، يعني انعكاس التحكم السماح لكود آخر بالاتصال بك بدلاً من الإصرار على إجراء الاستدعاء. مثال على عكس التحكم بدون حقن التبعية هو نمط طريقة القالب. هنا، يتم تحقيق تعدد الأشكال من خلال التصنيف الفرعي، أي الميراث. يطبق حقن التبعية انعكاس التحكم من خلال التكوين، لذلك غالبًا ما يكون مطابقًا لنمط الإستراتيجية، ولكن في حين أن نمط الإستراتيجية مخصص للتبعيات لتكون قابلة للتبادل طوال عمر الكائن، في حقن التبعية، قد يتم استخدام مثيل واحد فقط من التبعية هذا لا يزال يحقق تعدد الأشكال، ولكن من خلال التفويض والتكوين. أطر التطبيقات مثل CDI وتنفيذها مثل Weld وسبرينغ و Guice واطار عمل بلاي و Salta و Glassfish HK2 و Dagger وإطار التوسعة المدار (MEF) تدعم حقن التبعية ولكن غير الزامية للقيام بحقن التبعية.   فيUML الرسم التخطيطي لصنف أعلاه، لا يقوم صنف codice_1 الذي يتطلب كائنات codice_2 و codice_3 بإنشاء صنفيcodice_4 و codice_5 مباشرة. بدلاً من ذلك، يقوم صنف codice_6 بإنشاء الكائنات وحقنها في codice_1، مما يجعل codice_1 مستقلًا عن كيفية إنشاء الكائنات (أي الأصناف الملموسة التي يتم إنشاء مثيل لها). يوضح الرسم التخطيطي لتسلسل UML تفاعلات وقت التشغيل يقوم كائن codice_6 بإنشاء كائنات codice_4 و codice_5. بعد ذلك، يقوم codice_6 بإنشاء كائن codice_1 وإدخال كائنات codice_4 و codice_5.  بدون حقن التبعية  في مثال جافا التالي، يحتوي صنف على خدمة متغير عضو تمت تهيئته بواسطة مُنشئ.  يتحكم العميل في تنفيذ الخدمة المستخدمة ويتحكم في بنائها. في هذه الحالة، يُقال أن العميل لديه تبعية ذات كود صلب على.   // An example without dependency injection public class Client {  باستخدام التقنيات المختلفة الموضحة والموضحة في الأقسام الفرعية أدناه..  هناك ثلاث طرق على الأقل يمكن لكائن العميل تلقي مرجع لوحدة خارجية:   من الممكن أن يكون لأطر حقن التبعية أنواع أخرى من "الحقن" بخلاف تلك المذكورة أعلاه. قد تستخدم أطر الاختبار أيضًا أنواعًا أخرى. بعض أطر الاختبار الحديثة لا تتطلب حتى أن يقبل العملاء بنشاط حقن التبعية وبالتالي جعل الكود القديم قابل للاختبار. على وجه الخصوص، في لغة جافا، من الممكن استخدام الانعكاس لجعل السمات الخاصة عامة عند الاختبار وبالتالي قبول الحقن عن طريق التعيين.  لا تقدم بعض محاولات عكس التحكم الإزالة الكاملة للتبعية، ولكن بدلاً من ذلك ببساطة استبدال أحد أشكال التبعية بأخرى. كقاعدة عامة، إذا لم يتمكن المبرمج من النظر إلى شيء سوى كود العميل والإخبار عن إطار العمل المستخدم، عندئذٍ يكون لدى العميل اعتماد مرتبط بالكود الصلب على الإطار.  تتطلب هذه الطريقة من العميل توفير معلمة في مُنشئ للتبعية.  // Constructor Client(Service service) {  تتطلب هذه الطريقة من العميل توفير طريقة ضبط للتبعية.  // Setter method public void setService(Service service) {  ببساطة العميل هو الذي ينشر واجهة الدور لطرق تعيين تبعيات العميل. يمكن استخدامه لتحديد الطريقة التي يجب أن يتحدث بها الحاقن مع العميل عند حقن التبعيات.  // Service setter interface. public interface ServiceSetter {  // Client class public class Client implements ServiceSetter {  يُفضل عند إنشاء جميع التبعيات أولاً لأنه يمكن استخدامها لضمان أن يكون كائن العميل دائمًا في حالة صالحة، على العكس من ذلك هو أن تكون بعض مراجع التبعية الخاصة به خالية (لم يتم تعيينها). ومع ذلك، من تلقاء نفسها، تفتقر إلى المرونة لتغيير تبعياتها في وقت لاحق. يمكن أن تكون هذه خطوة أولى نحو جعل العميل غير قابل للتغيير وبالتالي خيط آمن.  // Constructor Client(Service service, Service otherService) {  يتطلب من العميل توفير طريقة ضبط لكل تبعية. وهذا يعطي حرية التلاعببحالة المراجع التبعية في أي وقت. يوفر هذا المرونة، ولكن إذا كان هناك أكثر من تبعية واحدة يجب حقنها، فمن الصعب على العميل التأكد من حقن جميع التبعيات قبل أن يتم توفير العميل للاستخدام.  // Set the service to be used by this client public void setService(Service service) {  // Set the other service to be used by this client public void setOtherService(Service otherService) { // Set the service to be used by this client public void setService(Service service) {  // Set the other service to be used by this client public void setOtherService(Service otherService) {  // Check the service references of this client private void validateState() {  // Method that uses the service references public void doSomething() {  تتمثل ميزة حقن الواجهة في أن التبعيات يمكن أن تكون جاهلة تمامًا بعملائها، ومع ذلك لا يزال بإمكانها تلقي مرجع إلى عميل جديد واستخدامه، وإرسال مرجع إلى الذات إلى العميل. بهذه الطريقة، تصبح التبعيات عن طريق الحقن. الفكرة هي أن طريقة الحقن (التي يمكن أن تكون مجرد طريقة ضبط كلاسيكية) يتم توفيرها من خلال واجهة.  لا يزال هناك حاجة إلى مجمعلتعريفالعميل وتبعياته. سيأخذ المُجمِّع مرجع إلى العميل، ويحولها إلى واجهة المحدد التي تعيّن تلك التبعية وتمريرها إلى كائن التبعية هذا الذي يتحول ويمرر مرجع إلى الذات إلى العميل..  لكي يكون لحقن الواجهة قيمة، التبعية يجب أن تقوم بشيء، بالإضافة إلى إرجاع مرجع لنفسها.. يمكن أن يكون هذا بمثابة مصنع أو مجمع فرعي لحل تبعيات أخرى، وبالتالي تجريد بعض التفاصيل من المجمع الرئيسي.. يمكن أن يكون عدًا مرجعيًا حتى تعرف التبعية عدد العملاء الذين يستخدمونه. إذا احتفظت التبعية بمجموعة من العملاء، فيمكنها لاحقًا حقنهم جميعًا بمثيل مختلف عن نفسها  // Service setter interface. public interface ServiceSetter {  // Client class public class Client implements ServiceSetter {  // Injector class public class ServiceInjector {  // Service classes يعد التجميع يدويًا داخل الطريقة (الدالة) الرئيسية إحدى طرق تنفيذ حقن التبعية .  public class Injector {  ينشئ المثال أعلاه الرسم البياني للكائن يدويًا ثم يستدعيه عند نقطة واحدة لبدء العمل. من المهم ملاحظة أن هذا الحاقن ليس نقيًا. يستخدم أحد الكائنات التي يقوم ببنائها. لها علاقة بناء فقط مع ExampleService ولكنها تمزج البناء واستخدام العميل. لا ينبغي أن يكون هذا شائعًا. ومع ذلك، لا مفر منه. تمامًا مثل البرمجيات الموجهة للكائنات تحتاج إلى طريقة ثابتة غير موجهة للكائنات مثل ()main للبدء، يحتاج الرسم البياني للكائن المحقون بالتبعية إلى نقطة إدخال واحدة على الأقل (يفضل واحدة فقط) لبدء كل شيء.  قد لا يكون هذا البناء اليدوي في الطريقة الرئيسية مباشرأ وقد يتضمن استدعاء بناة أو مصانع أو أنماط بناء أخرى أيضًا. يمكن أن يكون هذا متقدمًا ومجرّدًا إلى حد ما. يتم تجاوز الخط من حقن التبعية اليدوي إلى حقن تبعية الإطار بمجرد أن كود البناء لم يعد مخصصًا للتطبيق بل أصبح عالميًا).  يمكن لإطارات مثل سبرينغ إنشاء هذه الكائنات نفسها وتوصيلها معًا قبل إرجاع مرجع إلى العميل. يمكن نقل جميع الإشارة إلى ExampleService الملموسة من الكود إلى بيانات التكوين.  import org.springframework.beans.factory.BeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;  public class Injector {  تسمح إطارات مثل سبرينغ بتفريغ تفاصيل التجميع في ملفات التكوين يقوم هذا الكود (أعلاه) ببناء الكائنات توصيلها معًا وفقًا لـ Beans.xml (أدناه). لا تزال خدمة قيد الإنشاء على الرغم من أنها مذكورة أدناه فقط. يمكن تعريف الرسم البياني للكائن الطويل والمعقد بهذه الطريقة، والصنف الوحيد المذكور في الكود ستكون هي صنف طريقة الإدخال، وهي في هذه الحالة (دالة تحية) ()greet.  </beans>  في المثال أعلاه، لم يكن يتعين على العميل والخدمة الخضوع لأية تغييرات يوزودها إطار سبرينغ. يسمح لهم بالبقاء كبوجو بسيطة. يوضح هذا كيف يمكن لspring أن يربط الخدمات والعملاء الذين يجهلون تمامًا وجودها. لا يمكن قول ذلك إذا تمت إضافة التعليقات التوضيحية الخاصة بSpring إلى الأصناف. من خلال منع التعليقات التوضيحية الاستدعاءات الخاصة بسبرينغ من الانتشار بين العديد من الأصناف، يظل النظام معتمدًا بشكل فضفاض فقط على سبرينغ. . ويمكن القول أيضًا أنه عند إعادة البناءإلى إطارآخر، فإن إزالة التعليقات التوضيحية المحددة للإطار ستكون جزءًا بسيطًا من المهمة  import org.springframework.beans.factory.BeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext;  public class Injector {  import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration;  @ComponentScan public class MyConfiguration {  @Component public class ExampleService { لا تختلف تنفيذات الحاقن المختلفة (المصانع، مواقع الخدمة، وحاويات حقن التبعية فيما يتعلق بحقن التبعية. ما يحدث فرقاً هو المكان الذي يسمح لهم باستخدامه. قم بنقل الاستدعاءات إلى المصنع أو محدد الخدمة خارج العميل وإلى الرئيسية والمفاجئ الرئيسي يجعل حاوية حقن التبعية جيدة إلى حد ما. من خلال نقل كل المعرفة عن الحاقن إلى الخارج، يتم ترك عميل نظيف، خالٍ من المعرفة بالعالم الخارجي. ومع ذلك، يمكن اعتبار أي كائن يستخدم كائنات أخرى عميلاً. الكائن الذي يحتوي على main ليس استثناء. هذا الكائن الرئيسي لا يستخدم حقن التبعية. في الواقع استخدام نمط محدد مواقع الخدمة. لا يمكن تجنب ذلك لأنه يجب أن يتم اختيار تنفذيات الخدمة في مكان ما.  لا يؤدي إخارج التبعيات إلى ملفات التكوين إلى تغيير هذه الحقيقة. ما يجعل هذه حقاً جزءًا من التصميم الجيد هو أن محدد الخدمة لا ينتشر في جميع أنحاء قاعدة الكود. يقتصر على مكان واحد لكل تطبيق. هذا يترك بقية الكود الاساسي متاح لاستخدام حقن التبعية لعملاء (نظيفين).  كانت الأمثلة حتى الآن أمثلة بسيطة للغاية حول إنشاء سلسلة (سلسلة نصية). ومع ذلك، يمكن أنه يكون نمط حقن التبعية أكثر فائدة عند إنشاء رسم بياني للكائن حيث تتواصل الكائنات عبر الرسائل.  ستستمر الكائنات التي تم إنشاؤها في main طوال عمر البرنامج. النمط النموذجي هو إنشاء الرسم البياني ثم استدعاء طريقة واحدة على كائن واحد لإرسال تدفق التحكم في الرسم البياني للكائن. تمامًا كما في main أن نقطة الدخول إلى الكود الثابت، فإن هذه الطريقة هي نقطة الدخول إلى الكود غير الثابت للتطبيقات. public static void main(String[] args) throws IOException {  class Greeter {  في إطار عمل أنغولار، هناك ثلاث طرق فقط يمكن للمكون (الكائن أو الوظيفة) الوصول مباشرةً إلى تبعياته:   أول خيارين لإنشاء التبعيات أو البحث عنها ليسا الأمثل لأنهما يكودا التبعية بشكل ثابت للمكون.  . وهذا يجعل من الصعب، إن لم يكن من المستحيل، تعديل التبعيات. هذا يمثل مشكلة خاصة في الاختبارات، حيث من المستحسن في الغالب توفير تبعيات وهمية لعزل الاختبار.  الخيار الثالث هو الأكثر قابلية للتطبيق، لأنه يزيل مسؤولية تحديد موقع التبعية من المكون. يتم تسليم التبعية ببساطة إلى المكون.  function SomeClass(greeter) {  SomeClass.prototype.doSomething = function(name) {  في المثال أعلاه، لا تهتم codice_17 بإنشاء أو تحديد مكان تبعية المحيي، بل يتم ببساطة تسليم المحيي عند إنشاء مثيل لها. هذا أمر مرغوب فيه، ولكنه يضع مسؤولية الحصول على التبعية على الكود الذي يبني بعض الأصناف codice_17.  لإدارة مسؤولية إنشاء التبعية، يحتوي كل تطبيق أنغولار جي إس، على حاقن. الحاقن هو محدد مواقع الخدمة المسؤول عن البناء والبحث عن التبعيات.  فيما يلي مثال على استخدام خدمة الحاقن:  // Provide the wiring information in a module var myModule = angular.module('myModule', []);  // Teach the injector how to build a greeter service. // greeter is dependent on the $window service. // The greeter service is an object that // contains a greet method. myModule.factory('greeter', function($window) {  قم بإنشاء حاقن جديد يمكنه توفير المكونات المعرفة في نموذج codice_19 وطلب خدمة المحيي من الحاقن. (يتم ذلك تلقائيًا تلقائيًا عن طريق أنغولار جي اس بووتستراب .  var injector = angular.injector(['myModule', 'ng']); var greeter = injector.get('greeter'); <div ng-controller="MyController"> </div>  function MyController($scope, greeter) {  عندما يقوم أنغلار جي إس، بتجميع HTML، فإنه يعالج توجيه codice_20، والذي بدوره يطلب من الحاقن إنشاء مثيل من وحدة التحكم وتبعياتها injector.instantiate(MyController); تمثيل صنف، فيمكنه تلبية جميع تبعيات codice_21 دون أن تعرف وحدة التحكم عن الحاقن. يعلن كود التطبيق ببساطة التبعيات التي يحتاجها، دون الحاجة إلى التعامل مع الحاقن. هذا الإعداد لا يخالف قانون ديميتر.  مثال على حقن المنشئ، حقن المعيّن وحقن الواجهة على (#C)  using System;  namespace DependencyInjection