Appearance
依赖导致原则
- 高层模块不依赖低层模块,两者都应该依赖其抽象;
- 抽象不应该依赖细节,细节应该依赖于抽象
- 简单的说:就是要求对抽象进行变成,不要对实现进行编程,这样就降低了客户与实现模块间的耦合
例子:
组装一天电脑,需要cpu、硬盘、内存条...。只有这些配置组装在一起,计算机才能正常的运行。选择cpu有很多选择,如Intel,AMD等;硬盘可以选择希捷、西数等;内存条可以选择金士顿、海盗船等
原始版本
CPU接口
java
package com.huangjiliang.design.heima.principle.demo;
public interface Cpu {
/**
* CPU运行
*/
void run();
}
硬盘接口
java
package com.huangjiliang.design.heima.principle.demo;
public interface HardDisk {
/**
* 硬盘保存数据
* @param data
*/
void save(String data);
/**
* 硬盘获取数据
* @return
*/
String get();
}
内存接口
java
package com.huangjiliang.design.heima.principle.demo;
public interface Memory {
/**
* 内存保存数据
*/
void save(String data);
}
IntelCpu
java
package com.huangjiliang.design.heima.principle.demo;
public class IntelCpu implements Cpu{
@Override
public void run() {
System.out.println("英特CPU在运行");
}
}
希捷硬盘
java
package com.huangjiliang.design.heima.principle.demo;
/**
* 希捷硬盘
*/
public class XijieHardDisk implements HardDisk{
@Override
public void save(String data) {
System.out.println("使用希捷硬盘存储数据:" + data);
}
@Override
public String get() {
System.out.println("希捷硬盘读取数据");
return "希捷";
}
}
金士顿内存条
java
package com.huangjiliang.design.heima.principle.demo;
/**
* 金士顿内存
*/
public class KingstonMemory implements Memory{
@Override
public void save(String data) {
System.out.println("金士顿内存存数数据" + data);
}
}
聚合具体成员变量的电脑类
java
package com.huangjiliang.design.heima.principle.demo;
import lombok.AllArgsConstructor;
/**
* 依赖具体的电脑类
*/
@AllArgsConstructor
public class ComputeOrigin {
private XijieHardDisk xijieHardDisk;
private IntelCpu intelCpu;
private KingstonMemory kingstonMemory;
/**
* 电脑运行
*/
public void run() {
System.out.println("电脑运行");
intelCpu.run();
kingstonMemory.save("内存条数据");
xijieHardDisk.save("硬盘保存数据");
}
}
类图
分析
以上代码可以看到已经组装了一台电脑,但是似乎组装的电脑的cpu只能使用英特cpu、内存条只能使用金士顿、硬盘只能使用希捷,这对用户肯定是不友好的,用户有了机箱肯定是按照自己的洗好,选择自己喜欢的配置
根据依赖倒置原则进行改进:Compute电脑类依赖各个配件的接口,而不是各个配件的具体实现类
改进版本
ComputeOrigin =》 ComputeImprove
package com.huangjiliang.design.heima.principle.demo;
import lombok.AllArgsConstructor;
/**
* 依赖各个配件抽象的电脑类
*/
@AllArgsConstructor
public class ComputeImprove {
private Cpu cpu;
private HardDisk hardDisk;
private Memory memory;
/**
* 电脑运行
*/
public void run() {
System.out.println("电脑运行");
cpu.run();
memory.save("内存条数据");
hardDisk.save("硬盘保存数据");
}
}
UML
分析
- 因为电脑类不是依赖配件的具体,而是依赖于抽象,所以用户组装电脑的时候可以选择抽象的具体实现类
- 面向对象的开发很好的解决了这个问题,一般情况下的抽象变化概率很小,让用户程序依赖于抽象,实现的细节也依赖于抽象。就是实现细节不断变动,只要抽象不变,客户程序就不需要变化。这大大降低了客户程序于实现细节的耦合度