依赖倒置原则就是抽象类和接口在使用时的一些规范和建议,我们的应用上层模块不直接依赖于下层模块,不具体依赖某个类或者对象,而是依赖于某个抽象。


接着上一节的Demo,我们有3个手机的对象。分别是LumiaPhone,Galaxy,ApplePhone,现在我们新增一个Student学生类,学生会使用手机。有可能使用LumiaPhone手机,也有可能使用Galaxy,也有可能使用

ApplePhone,那我们的Student看起来的得实现成这样:

publicclassStudent{publicintId{get;set;}publicstringName{get;set;}publicvoidPlayPhone(LumiaPhonelumiaPhone){Console.WriteLine($"{Name}use{lumiaPhone.Name}");}publicvoidPlayApplePhone(ApplePhoneapplePhone){Console.WriteLine($"{Name}use{applePhone.Name}");}publicvoidPlayGalaxy(Galaxygalaxy){Console.WriteLine($"{Name}use{galaxy.Name}");}}

具体使用时,我们可能会是这样: 先创建一个Student再根据学生使用的某种手机 调用不同的play方法

LumiaPhonelumiaPhone=newLumiaPhone();ApplePhoneapplePhone=newApplePhone();Galaxygalaxy=newGalaxy();Studentstudent=newStudent();student.PlayPhone(lumiaPhone);student.PlayApplePhone(applePhone);student.PlayGalaxy(galaxy);

这个时候假设Student旧的手机坏了,换了新的华为手机,那我们新增一个Honor对象

publicclassHonor{publicvoidSystem(){Console.WriteLine("HuaWeiHonor");}}

再修改Student类 新增一个方法

publicvoidPlayHonor(Honorhonor){Console.WriteLine($"{Name}use{honor.Name}");}

使用时

Honorhonor=newHonor();student.PlayHonor(honor);

手机有太多种类,每次新增对象我们都要在Student中新增方法 在调用处进行手机的实例化,维护起来非常麻烦,容易出错。不利于扩展,所以我们的Student 不应该依赖于具体的类,而是应该依赖抽象上一遍提到的BasePhone,我们来改造下代码Student会变成这样

publicclassStudent{publicintId{get;set;}publicstringName{get;set;}publicvoidPlayPhone(BasePhonebasePhone){Console.WriteLine($"{Name}use{basePhone.Name}");}//publicvoidPlayPhone(LumiaPhonelumiaPhone)//{//Console.WriteLine($"{Name}use{lumiaPhone.Name}");//}//publicvoidPlayApplePhone(ApplePhoneapplePhone)//{//Console.WriteLine($"{Name}use{applePhone.Name}");//}//publicvoidPlayGalaxy(Galaxygalaxy)//{//Console.WriteLine($"{Name}use{galaxy.Name}");//}//publicvoidPlayHonor(Honorhonor)//{//Console.WriteLine($"{Name}use{honor.Name}");//}}

我们的调用处

static void Main(string[] args)

{

{

LumiaPhone lumiaPhone = new LumiaPhone();

ApplePhone applePhone = new ApplePhone();

Galaxy galaxy = new Galaxy();

Honor honor = new Honor();

Student student = new Student();

student.PlayPhone(lumiaPhone);

student.PlayPhone(applePhone);

student.PlayPhone(galaxy);

student.PlayPhone(honor);

//student.PlayPhone(lumiaPhone);

//student.PlayApplePhone(applePhone);

//student.PlayGalaxy(galaxy);

//student.PlayHonor(honor);

}



Console.ReadKey();

}

这个时候感觉Main还是依赖了具体的对象Student,以学生使用honor手机为例

BasePhonehonor=newHonor();Studentstudent=newStudent();student.PlayPhone(honor);

我们新增一个SimpleFactory及接口IPlayPhone

publicstaticclassSimpleFactory{publicstaticBasePhoneCreatePhone(){returnnewHonor();}publicstaticStudentCreateStudent(){returnnewStudent();}}


publicinterfaceIPlayPhone{voidPlayPhone(BasePhonebasePhone);}

那我们的Main方法则变成

staticvoidMain(string[]args){{BasePhonehonor=SimpleFactory.CreatePhone();IPlayPhonestudent=SimpleFactory.CreateStudent();student.PlayPhone(honor);//Honorhonor=newHonor();//Studentstudent=newStudent();//student.PlayPhone(honor);//student.PlayPhone(lumiaPhone);//student.PlayApplePhone(applePhone);//student.PlayGalaxy(galaxy);//student.PlayHonor(honor);}Console.ReadKey();}




我在这个demo SimpleFactory里直接返回了一个对象,项目中是可以通过读取配置文件反射来构造实的
这样只要通过改配置文件 就可以实现学生更换手机的功能,同样通过配置文件 也可以实现 老师使用手机只要我们新增一个Teacher类 实现IPlayPhone接口。其他代码不需要任何改动, 这就是我们原则 依赖抽象或接口 而不应该依赖于具体的细节的好处, 这里学生,老师其实就是上层,而我们的手机则是下层,上层不应该依赖下层 而是应该依赖抽象