معرفی الگوی Dependency Injection

یکی از اهداف برنامه نویسی شی گرا، کم کردن وابستگی اشیا به یکدیگر است. این به این معنی است که اگر در یک کلاس(کلاس اصلی) نیاز به استفاده از قابلیت های کلاس دیگر(کلاس کمکی) بود، به نحوی این کار انجام شود که با تغییر در کلاس کمکی، کلاس اصلی نیاز به تغییر نداشته باشد. و اینکه اگر نیاز شد بعد ها عملکرد کلاس کمکی تغییر کند، بدون تغییر در کلاس اصلی این کار انجام شود.
برای مثال فرض کنید در حال طراحی کلاسی هستیم که امکان تغییر پسورد را به کاربر میدهد. میخاهیم بعد از اینکه پسورد تغییر کرد با ایمیل به کاربر خبر داده شود. در نگاه اول خبر رسانی یکی از قابلیت های کلاس اصلی ما به نظر میرسد.
اما با کمی دقت متوجه میشویم که این قسمت از برنامه میتواند ماژول جدایی باشد و فقط در برنامه از آن استفاده شود. و ممکن است استراتژی ما برای خبر رسانی در آینده تغییر کند مثلا اعلام تغییرات به وسیله SMS انجام گیرد نه ایمیل.اینجاست که  DI وارد کار میشود.
مثالی دیگر از DI در طراحی برنامه های چند لایه است. هنگام تعیرف کلاس های BL نیاز به این دارید که کلاس DA که از آن استفاده میکنید را به برنامه معرفی کنید. هنگام استفاده از DI به جای تعریف یک متغیر از جنس کلاس DA مثلا SQLRepositoryدر BL تنها کافی است یک متغیر از جنس IRepository در این کلاس تعیرف کنید و بعدا در هنگام استفاده از این کلاس تعیین کنید که این Repository از چه جنسی است مثلا SQLRepository یا AccessRepository.
در یک طراحی که از DI بهره میبرد قسمت های زیر وجود دارند
- شی وابسته
- تعریف وابستگی ها
- تامین کننده وابستگی ها که عموما محل استفاده از شی وابسته است.
در پیاده سازی DI دو استراتژی جداگانه ممکن است استفاده شود. اولی Constructor Injection و دیگری Setter Injection.  از مزایای روش اول این است که نمیتوان بدون تعیین وابستگی از کلاس مورد نظر استفاه برد و جلوی خطاهای انسانی گرفته میشود. اما از مزایای روش دوم میتوان به عدم نیاز به تغییر سازنده برنامه و عدم نیاز به ساخت اشیاء سنگین تا زمان نیاز به آنها اشاره کرد.
در زیر یک مثال ساده از کاربرد این تکنیک در برنامه نویسی چند لایه را که در مثال بالا ذکر شد میبینیم.



public class Order
{
public int OrderId { get; set; }
public DateTime OrderDate { get; set; }
}
 
public interface IOrderRepository
{
IQueryable Orders{ get; } 
}
 
public class FakeOrderRepository:IOrderRepository
{
private static IQueryable fakeOrders = new List { 
new Order { OrderId = 1, OrderDate = new DateTime(2011,1,1) }, 
new Order { OrderId = 2, OrderDate = new DateTime(2011,1,2) }, 
new Order { OrderId = 3, OrderDate = new DateTime(2011,1,3) } 
}.AsQueryable();
 
public IQueryable Orders
{
get { return fakeOrders; }
}
}
 
public class SQLOrderRepository:IOrderRepository
{
private Table OrdersTable;
public SQLOrderRepository(string connectionString) 
{
OrdersTable = (new DataContext(connectionString)).GetTable(); 
}
public IQueryable Orders
{
get { return OrdersTable; }
}
}
 
public class OrderManager
{
private IOrderRepository _orderRepository;
public OrderManager(IOrderRepository orderRepository)
{
this._orderRepository = orderRepository;
}
 
public List GetList()
{
return _orderRepository.Orders.ToList();
}
}
در این مثال در زمان اجرا هر یک از کلاس های DA را که بخاهیم میتوانیم به BL ارسال کنیم. * فریم ورک های بسیاری برای کمک به پیاده سازی بهتر این تکنیک وجود دارد که میتوان ninject اشاره کرد.

0 نظرات: