定义
上层模块不应该依赖底层模块,它们都应该依赖于抽象,抽象不应该依赖于细节,细节应该依赖于抽象。
简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模块间的耦合。
代码实现
假设现在要叫朋友John上号,选择通过微信发消息。
不使用依赖倒转原则
定义微信类,用来发消息
/**
* @author John117
* @date 2022/05/23 17:30
*/
public class WeChat {
public void sendMessage(){
System.out.println("微信:速度上号");
}
}
定义John类,用来接受消息
/**
* @author John117
* @date 2022/05/23 17:32
*/
public class John {
public void getMessage(WeChat weChat){
weChat.sendMessage();
}
}
测试
/**
* @author John117
* @date 2022/05/23 17:35
*/
public class Test {
public static void main(String[] args) {
new John().getMessage(new WeChat());
}
}
这种设计有个很大的缺点,假如此时想再添加一个通讯方式比如钉钉,在定义钉钉类后,还要去修改John的接受方式。在现实工程中,这种做法工程量太大了。
使用依赖倒转原则
面向接口,定义一个消息类接口IMessage
/**
* @author John117
* @date 2022/05/23 17:35
*/
public class Test {
public static void main(String[] args) {
new John().getMessage(new WeChat());
}
}
定义WeChat类,WeChat实现IMessage
/**
* @author John117
* @date 2022/05/23 17:37
*/
public class WeChat implements IMessage{
@Override
public void sendMessage() {
System.out.println("微信:速度上号");
}
}
定义John
/**
* @author John117
* @date 2022/05/23 17:37
*/
public class John {
public void getMessage(IMessage message){
message.sendMessage();
}
}
测试
/**
* @author John117
* @date 2022/05/23 17:39
*/
public class Test {
public static void main(String[] args) {
new John().getMessage(new WeChat());
}
}
此时,如果想在添加一个通讯方式钉钉,只需定义DingDing类,使DingDing实现IMessage
/**
* @author John117
* @date 2022/05/23 17:39
*/
public class DingDing implements IMessage{
@Override
public void sendMessage() {
System.out.println("钉钉:速度上号");
}
}
在测试类,传入相应消息实体类即可
public class Test {
public static void main(String[] args) {
new John().getMessage(new WeChat());
new John().getMessage(new DingDing());
}
}
结论
-
低层模块尽量都要有抽象类或接口,或者两者都有。
-
程序稳定性更好,变量的声明类型尽量是抽象类或者接口,这样我们的变量引用和实际对象间,就存在一个缓冲层, 利于程序扩展和优化。