Dependence Inversion Principle 简称 DIP
抽象不应该依赖于细节,细节应该依赖于抽象
- 高层模块不应该依赖低层模块,两者都应该依赖其抽象.不可分割的原子逻辑就是低层模式,原子逻辑组装成的就是高层模块。
- 抽象不应该依赖细节。java 中,抽象 -> 接口或抽象类;细节 -> 实现类
- 细节应该依赖抽象
精简一下就是 「面向接口编程」 ,是面向对象设计的精髓之一,可以减少类间的耦合性,提高系统的稳定性,降低并行开发引起的风险, 在 java 中的表现:
- 模块间依赖通过抽象(接口)发生,实现类之间不直接依赖
- 接口或抽象类不依赖于实现类
- 实现类依赖于接口或抽象类
这样的好处:解耦类和类之间的关系,不然你依赖另外一个类的话,另外一个类修改,你这里也要修改,
而如果依赖接口,那么需要修改的话,只要在实现类修改,依赖类不需要修改。
代码讲解
对于下面的代码:
public class StringProcessor { //具体类
private final StringReader stringReader; //具体类
private final StringWriter stringWriter; //具体类
//通过构造函数来注入依赖组件
public StringProcessor(StringReader stringReader, StringWriter stringWriter) {
this.stringReader = stringReader;
this.stringWriter = stringWriter;
}
public void readAndWrite() {
stringWriter.write(stringReader.getValue());
}
//测试用例
public static void main(String[] args) {
StringReader sr = new StringReader();
sr.read("1111111");
StringWriter sw = new StringWriter();
StringProcessor sp = new StringProcessor(sr,sw);
sp.readAndWrite();
}
}
优点就是逻辑简单,一眼就能看明白,但是耦合严重,这时,如果我们想要复用 StringProcessor 组件,则需要在引入的地方写很多重复代码。
public interface StringProcessor {
void readAndWrite(StringReader stringReader, StringWriter stringWriter);
}
public interface StringReader {
void read(String path);
String getValue();
}
public interface StringWriter {
void write(String value);
}
public class StringProcessorImpl implements StringProcessor {
//StringReader 是接口
//StringWriter 是接口
@Override
public void readAndWrite(StringReader stringReader, StringWriter stringWriter) {
stringWriter.write(stringReader.getValue());
}
public static void main(String[] args) {
StringReader sr = new StringReaderImpl();
sr.read("333333");
StringWriter sw = new StringWriterImpl();
StringProcessor sp = new StringProcessorImpl();
sp.readAndWrite(sr,sw);
}
}
过去,StringProcessor 依赖于 StringReader 和 StringWriter 的具体实现,
而现在则是 StringProcessor 来定义一组抽象规则,由 StringReader 和 StringWriter 来依赖。