سلام
اصل Dependency Inversion صرفا باعث کاهش وابستگی ها میشه و وابستگی رو به صفر نمیرسونه درسته؟
مثلا ماژول سطح بالا به یک انتزاعی وابسته هست و ماژول های سطح پایین هم میان اون انتزاع رو implements میکنن و جزئیات رو پیاده سازی می کنن
کلاس سطح پایین z علاوه بر متد هایی که باید طبق قرارداد پیاده سازی کنه میتونه متدهای مخصوص به خود رو هم داشته باشه و اگه ما بیاییم تو کلاس سطح بالا از این متدهای که مخصوص کلاس z هست استفاده کنیم یجور وابستگی این وسط ایجاد میشه
درود
این اصل به ما میگه که کدهای ما باید به abstraction وابسته باشن ن concreate یا همون پیاده سازی، به طور کلی ینی اینکه کلاس های رده بالا یا پدر نباید به کلاس های فرزند وابستگی داشته باشند و این قضیه باید کاملا برعکس باشه و کلاس های فرزند باید به abstraction وابسته باشند
interface MailDriverInterface
{
public function send();
}
class SMTPMailDriver implements MailDriverInterface
{
public function send()
{
return 'use php mail() method';
}
}
class SendWelcomeEmail
{
private $mailDriver;
public function __construct(MailDriverInterface $mailDriver)
{
$this->mailDriver = $mailDriver;
}
public function send()
{
$this->mailDriver->send();
}
}
MailDriverInterface یک interfaceی هستش که میگه هر کلاس که بخواد من رو پیاده سازی کنه باید حتما باید متد send رو پیاده سازی کنه و همین باعث میشه که تمامی کلاس های فرزند این interface از تمامی متدهاش پیروی کنند و پیاده سازیش کنن که دقیقا کلاس SMTPMailDriver اومده همچین کاری رو کرده
مزیتش چیه؟ میزیتش اینکه ما اگه بخواهیم بعدا نوع دیگه ای از ارسال ایمیل رو اضافه کنیم دیگه میدونیم که باید داخلش متد send رو داشته باشیه و ما کاری به نوع پیاده سازیش نداریم چون فقط برای ما مهمه که اون کلاس یک ایمیل رو send کنه
حالا اگه داخل کلاس SendWelcomeEmail یا هر کلاس دیگه ای نیاز بود یک ایمیلی ارسال کنیم میایم به سادگی از طریق constract اون کلاس وابستگی رو تزریق میکنیم و داخل یکی از متدهای کلاس خیلی ساده چون میدونیم قراردادی وجود داره که باید همه درایورهای ارسال ایمیل متد send رو داشته باشیند با خیال راحت متد Send رو صدا میزنیم
ممنون از پاسختون
« ینی اینکه کلاس های رده بالا یا پدر نباید به کلاس های فرزند وابستگی داشته باشند » این بخش بنظرم اشتباه هست کلاس سطح بالا کلاسی هست که عملی رو با استفاده از یک ابزار انجام میده و کلاس سطح پایین کلاسی ابزاری هست که برای اجرای عملی موردنیاز هست
داخل همین مثالی که خودتون زدید کلاس SendWelcomeEmail یک کلاس سطح بالاست که برای ارسال email از کلاس سطح پایین SMTPMailDriver استفاده میکنه
بعدش مزیت Dependency Inversion اینه که اگه بخواهیم بعدا نوع دیگه ای از ارسال ایمیل رو اضافه کنیم دیگه میدونیم که باید داخلش متد send رو داشته باشه ؟!
یا اینکه Dependency Inversion این مزیت رو به ما میده تا با تعریف یک interface وابستگی کلاس سطح بالا به کلاس های سطح پایین رو کاهش بدیم اینطوری کلاس سطح بالامون میتونه براحتی با هر کلاسی که interface ما رو پیاده سازی کرده کار کنه
موردی که شما بهش اشاره کردید هم dependency inversion و هم dependency injection رو درگیر میکنه، حالا ینی چی
ما توی dependency inversion میگیم این وابستگی نباید به صورت وارونه از سمت فرزند به پدر باشه بلکه باید از پدر به فرزند باشه، مثل آبشار بهش نگاه کنید که آبشار همون کلاس پدر ماست که داره به رودخونه پایینش که کلاس فرزند میشه آب میرسونه
و توی dependency injection به صورت که تزریق وابستگی باید جوری باشه که فرزند تعیین نکنه که دقیقا چی میخواد ما باید بهش چیزی که نیاز داره رو بدیم، ینی اگه قراره کلاسی داخل کلاس فرزند new بشه بهتره که از طریق construct بهش object کلاسی رو پاس بدیم به جای اینکه خود فرزند بیاد کلاسی رو داخل خودش new کنه
سر همین دو اصل مهم ما توی لاراول چیزی به اسم IOC رو داریم که اومده به شکل کامل این مبحث رو توی هسته لاراول پیاده سازی کرده
من این دوتا مورد رو خیلی بیشتر با مثال داخل این تاپیک توضیخ دادم و گفتم که ico چیه https://7learn.ac/community/ioc-%D8%AF%D9%82%DB%8C%D9%82%D8%A7-%DA%86%DB%8C%D9%87--2LPKL