مشخصات مقاله
-
858
-
0.0
-
2403
-
0
-
0
بیان اصل وارونگی وابستگی
اصل وارونگی وابستگی
در فصل قبل آموختیم که چگونه با استفاده از الگوی Factory اصل IoC را پیاده سازی کنیم و به اولین سطح از طراحی دارای همراهی آزادانه دست یافتیم. در اینجا می خواهیم به عنوان دومین قدم به سمت کلاس های دارای همراهی آزادانه، در رابطه با اصل وارونگی وابستگی و چگونگی پیاده سازی آن بیاموزیم.
ابتدا، اجازه دهید اصل وارونگی وابستگی (DIP) را تعریف کنیم.
DIP یکی از اصول شیء گرای SOLID است که توسط آقای رابرت مارتین (معروف به عمو باب) ابداع شده است.
تعریف DIP
- ماژول های سطح بالا نباید به ماژول های سطح پایین وابسته باشند، بلکه هردو باید به انتزاع وابستگی داشته باشند.
- انتزاعات نباید به جزئیات وابسته باشند. بلکه جزئیات هستند که باید به انتزاعات وابسته باشند.
برای درک بهتر DIP به مثال فصل قبل که در زیر آمده است توجه کنید.
public class CustomerBusinessLogic
{
public CustomerBusinessLogic()
{
}
public string GetCustomerName(int id)
{
DataAccess _dataAccess = DataAccessFactory.GetDataAccessObj();
return _dataAccess.GetCustomerName(id);
}
}
public class DataAccessFactory
{
public static DataAccess GetDataAccessObj()
{
return new DataAccess();
}
}
public class DataAccess
{
public DataAccess()
{
}
public string GetCustomerName(int id) {
return "Dummy Customer Name"; // get it from DB in real app
}
}
در این مثال، برای دستیابی به IoC ، الگوی factory را پیاده سازی کرده ایم. اما کلاس CustomerBusinessLogic از کلاس عینی DataAccess استفاده می کند. بنابراین، با وجود اینکه ما ایجاد شیء وابسته را به کلاس factory وارونه کرده ایم، هنوز این کلاس همراهی غیر آزادانه دارد.
بیایید در کلاس های DataAccess و CustomerBusinessLogic از DIP استفاده کنیم و همراهی آن ها را آزادانه تر نماییم.
با توجه به تعریف DIP یک ماژول سطح بالا نباید به ماژول های سطح پایین وابسته باشد، بلکه هر دو باید به انتزاع وابستگی داشته باشند. بنابراین، به عنوان اولین قدم مشخص کنید که کدام ماژول ها (کلاس ها) سطح بالا و کدام سطح پایین هستند. ماژول سطح بالا به ماژولی گفته می شود که به ماژول های دیگر وابسته است. در مثال ما CustomerBusinessLogic به کلاس DataAccess وابسته است. در نتیجه CustomerBusinessLogic یک ماژول سطح بالا و DataAccess ماژول سطح پایین است. در نتیجه با توجه به قانون اول DIP ، CustomerBusinessLogic نباید به کلاس عینی DataAccess وابسته باشد. بلکه هردو کلاس باید به انتزاع وابستگی داشته باشند.
قانون دوم DIP این است که انتزاعات نباید به جزئیات وابسته باشند، بلکه عکس این قضیه باید صادق باشد.
انتزاع چیست؟
انتزاع و لفافه بندی یا کپسوله سازی، جزء اصول مهم برنامه نویسی شیء گرا هستند. تعاریف مختلفی از طرف افراد زیادی برای انتزاع ارائه شده است. اما اجازه دهید به کمک مثال بالا انتزاع را بهتر درک کنیم.
در زبان انگلیسی، abstraction به معنی چیزی است که عینی نباشد. در زبان برنامه نویسی، کلاس های CustomerBusinessLogic و DataAccess عینی هستند. به این معنی که می توانیم اشیاء آن ها را ایجاد کنیم. بنابراین، انتزاع در برنام نویسی به ایجاد رابطی برای کلاس انتزاعی غیرعینی گفته می شود. این یعنی نمی توانیم شیئی از رابط یا کلاس انتزاعی را ایجاد کنیم. با توجه به تعریف DIP ، CustomerBusinessLogic (ماژول سطح بالا) نباید به کلاس عینی DataAccess (ماژول سطح پایین) وابسته باشد، بلکه هر دو باید به انتزاعات یا همان رابط و یا کلاس انتزاعی وابستگی داشته باشند.
حالا چه چیزی باید در رابط (یا کلاس انتزاعی) وجود داشته باشد؟ همانطور که می بینید، CustomerBusinessLogic از متد GetCustomerName() مربوط به کلاس DataAccess استفاده می کند (در حالت واقعی داخل کلاس DataAccess متدهای مرتبط به مشتری زیادی وجود خواهند داشت). همانطور که در زیر مشاهده می کنید، متد GetCustomerName(int id) را در رابط اعلان کرده ایم.
public interface ICustomerDataAccess
{
string GetCustomerName(int id);
}
حالا، نوبت به پیاده سازی ICustomerDataAccess در کلاس CustomerDataAccess می رسد (پس به جای کلاس DataAccess بیایید کلاس جدید CustomerDataAccess را تعریف کنیم). مانند زیر:
public class CustomerDataAccess: ICustomerDataAccess
{
public CustomerDataAccess()
{
}
public string GetCustomerName(int id) {
return "Dummy Customer Name";
}
}
حالا باید مانند زیر کلاس factory مان را تغییر دهیم تا به جای کلاس عینی DataAccess، ICustomerDataAccess را برگشت دهد.
public class DataAccessFactory
{
public static ICustomerDataAccess GetCustomerDataAccessObj()
{
return new CustomerDataAccess();
}
}
حالا کلاس CustomerBusinessLogic را مانند زیر به گونه ای تغییر دهید که این کلاس به جای کلاس عینی DataAccess از کلاس ICustomerDataAccess استفاده کند.
public class CustomerBusinessLogic
{
ICustomerDataAccess _custDataAccess;
public CustomerBusinessLogic()
{
_custDataAccess = DataAccessFactory.GetCustomerDataAccessObj();
}
public string GetCustomerName(int id)
{
return _custDataAccess.GetCustomerName(id);
}
}
بدین گونه DIP را در مثالی که ماژول سطح بالا (CustomerBusinessLogic) و ماژول سطح پایین (CustomerDataAccess) به انتزاع (ICustomerDataAccess) وابسته هستند، پیاده سازی کردیم. همچنین انتزاع (ICustomerDataAccess) به جزئیات (CustomerDataAccess) وابسته نیست، بلکه جزئیات هستند که به انتزاع وابستگی دارند.
DIP بحث شده تا به اینجا به صورت کامل در مثال زیر بررسی شده است.
مثال : پیاده سازی DIP
public interface ICustomerDataAccess
{
string GetCustomerName(int id);
}
public class CustomerDataAccess: ICustomerDataAccess
{
public CustomerDataAccess() {
}
public string GetCustomerName(int id) {
return "Dummy Customer Name";
}
}
public class DataAccessFactory
{
public static ICustomerDataAccess GetCustomerDataAccessObj()
{
return new CustomerDataAccess();
}
}
public class CustomerBusinessLogic
{
ICustomerDataAccess _custDataAccess;
public CustomerBusinessLogic()
{
_custDataAccess = DataAccessFactory.GetCustomerDataAccessObj();
}
public string GetCustomerName(int id)
{
return _custDataAccess.GetCustomerName(id);
}
}
مزیت های پیاده سازی DIP در مثال بالا این است که کلاس های CustomerBusinessLogic و CustomerDataAccess دارای همراهی آزادانه هستند. زیرا CustomerBusinessLogic به کلاس عینی DataAccess وابسته نیست. بلکه در عوض شامل مرجعی از رابط ICustomerDataAccess است. پس حالا، به راحتی می توانیم کلاس دیگری را استفاده کنیم که به کمک شیوه ی متفاوتی ICustomerDataAccess را پیاده سازی کند. اما هنوز به طور کامل به کلاس های دارای همراهی آزادانه دست نیافته ایم. زیرا کلاس CustomerBusinessLogic برای دریافت مرجع ICustomerDataAccess شامل کلاس Factory است. این همان جایی است که الگوی تزریق وابستگی می تواند به ما کمک کند. در فصل بعد نحوه ی استفاده از الگوی استراتژی و DI را با استفاده از مثال بالا خواهیم آموخت.
برای مطالعه سرفصل اصول و الگوهای طراحی شی گرا - Object Oriented Design Principles & Patterns کلیک نمایید .