به عبارت دیگر در طراحی ساخت یافته، کلاسهای سطح بالا، به کلاسهای سطح پایین وابستهاند. این مسئله دو مشکل را ایجاد میکند:
- هر تغییری در کلاسهای سطح پایین ممکن است باعث ایجاد اشکالی در کلاسهای سطح بالا گردد.
- استفادهی مجدد از کلاسهای سطح بالا در جاهای دیگر مشکل است؛ زیرا وابستگی مستقیمی به کلاسهای سطح پایین دارند.
یکی از اصول پنجگانهی طراحی برنامههای شیء گرا که با نام اصول SOLID شناخته میشوند، اصل «وارونگی وابستگیها» است که روشی برای مشکل جفت شدگی و وابستگی کلاسها به یکدیگر را به صورت تئوری ارائه میدهد.
- ماژولهای (کلاسهای) سطح بالا نباید به ماژولهای (کلاسهای) سطح پایین وابسته باشند و هر دو باید به انتزاعات وابسته باشند (برای مثال interfaceها).
- انتزاعات نباید وابسته به جزئیات باشند؛ بلکه جزئیات (پیاده سازی) باید وابسته به انتزاعات باشند.
شیء گرایی در واقع در مورد نحوهی جریان کنترل است. در اینجا اینترفیسها به ما کنترل کاملی را بر جریان کنترل (Flow of control) میدهند که با استفاده از این امکان میتوانیم از نوشتن کدهای جفت شده، شکننده و کلاسهایی یکبار مصرف، بپرهیزیم.
الگوی Dependency Injection
- کلاس کلاینت / Client Class : کلاس کلاینت (کلاس وابسته) کلاسی است که به کلاس سرویس وابسته است .
- کلاس سرویس / Service Class : کلاس سرویس (وابستگی) کلاسی است که یک سرویس را به کلاس کلاینت ارائه میدهد.
- کلاس تزریق کننده / Injector Class : کلاس تزریق کننده، نمونهای از کلاس سرویس را ساخته و به کلاس کلاینت، تزریق میکند.
شکل زیر وابستگی بین کلاسها را شرح میدهد:
همانطور که میبینید، کلاس Injector، نمونهای از کلاس سرویس را میسازد و آن را به نمونهای از کلاس Client تزریق میکند. با این کار، DI، وظیفهی ساخت یک نمونه از کلاس Service را از درون کلاس Client جدا میکند.
انواع تزریقات وابستگیها:
به صورت کلی به سه روش و در سه مکان، امکان تزریق وابستگی کلاس سرویس، درون کلاس کلاینت وجود دارد:
- تزریق درون سازنده / Constructor Injection : در تزریق درون سازنده، در سازندهی کلاس کلاینت، لیستی از سرویسهای مورد نیاز کلاس، که کلاس، برای عملکرد خود به آنها «وابسته» است، ثبت میشوند و کلاس Injector، سرویس (وابستگی) مورد نظر را درون سازندهی کلاس Client ارائه میدهد.
- تزریق درون Property کلاس / Property Injection : در این حالت که همچنین با نام (Setter Injection) هم شناخته میشود، تزریق کننده، وابستگی را به وسیلهی یک Property عمومی کلاس کلاینت ارائه میدهد.
- تزریق درون متد / Method Injection : در این حالت، خود کلاس کلاینت، یک پیاده سازی از یک interface را ارائه میکند که درون آن متدهایی برای ارائهی وابستگیها به کلاینت تعریف شدهاند. در این وضعیت، تزریق کننده از این اینترفیس برای ارائهی وابستگیها به کلاینت درون متدها، استفاده میکند.
Inversion of Control Container
- Dependency Injection
- Service Locator
به صورت کلی IoC Container ها سه وظیفهی اساسی را برعهده دارند:
- ثبت سرویس درون خود
- ساخت نمونههای مورد نظر از سرویسها و ارائه دادن آنها به کلاسهایی که نیاز دارند.
- از بین بردن نمونه سرویسهای ساخته شده (Dispose) کردن آنها .