理论知识
概念
- 高层模块不应该依赖于低层模块, 二者都应该依赖于抽象
- 实现应该依赖于抽象, 即稳定应该依赖于变化
- 面向接口编程
- 使用接口的目的是设计规范而不涉及细节
优点
稳定性强,不会因为低层模块的变化而需改变大量的高层模块
代码实现
不遵循依赖倒转原则
代码
package com.study.dependencyReverse;
public class DependencyReverse1 {
public static void main(String[] args) {
new Person().receive(new IPhone());
}
}
class IPhone {
public String getPhoneName() {
return "苹果手机";
}
}
class Person {
public void receive(IPhone i) {
System.out.println("我用" + i.getPhoneName() + "接电话");
}
}
分析
此时,看起来没啥问题,但是当我提出新的需求,新增小米手机和华为手机时,就需要改变Person类,重载receive方法(代码如下),破坏了框架稳定性。当系统很大时,逻辑就会出现混乱,维护较为困难
代码
package com.study.dependencyReverse;
public class DependencyReverse2 {
public static void main(String[] args) {
new Person1().receiveIphone(new IPhone1());
new Person1().receiveMiPhone(new MiPhone());
new Person1().receiveHWPhone(new HWPhone());
}
}
class IPhone1 {
public String getPhoneName() {
return "苹果手机";
}
}
class MiPhone {
public String getPhoneName() {
return "小米手机";
}
}
class HWPhone {
public String getPhoneName() {
return "华为手机";
}
}
class Person1 {
public void receiveIphone(IPhone1 i) {
System.out.println("我用" + i.getPhoneName() + "接电话");
}
public void receiveMiPhone(MiPhone m) {
System.out.println("我用" + m.getPhoneName() + "接电话");
}
public void receiveHWPhone(HWPhone h) {
System.out.println("我用" + h.getPhoneName() + "接电话");
}
}
遵循依赖倒转原则
代码
package com.study.dependencyReverse;
public class DependencyReverse3 {
public static void main(String[] args) {
new Person2().receive(new IPhone2());
new Person2().receive(new MiPhone1());
new Person2().receive(new HWPhone1());
}
}
interface IPhoneName{
String getPhoneName();
}
class IPhone2 implements IPhoneName {
@Override
public String getPhoneName() {
return "苹果手机";
}
}
class MiPhone1 implements IPhoneName {
@Override
public String getPhoneName() {
return "小米手机";
}
}
class HWPhone1 implements IPhoneName {
@Override
public String getPhoneName() {
return "华为手机";
}
}
class Person2 {
public void receive(IPhoneName i) {
System.out.println("我用" + i.getPhoneName() + "接电话");
}
}
分析
Person类依赖IPhoneName接口, 新增手机类型时只需要添加IPhoneName的实现类即可,不用修改高层模块,提高了稳定性和可维护性。