面向接口编程:依赖倒置原则的重要性
软件开发中,依赖倒置原则是面向对象编程中的重要设计原则之一。依赖倒置原则的核心思想是高层模块不应该依赖于低层模块,二者都应该依赖于抽象;面向接口编程正是基于这一原则。
面向接口编程可以更好地实现依赖倒置原则,通过定义接口来描述模块间的通信规范,从而降低模块间的耦合度。通过面向接口编程,可以实现系统的灵活性、可扩展性和可维护性。
举个例子,假设我们有一个系统由三个模块组成:模块A、模块B和模块C。在传统的面向实现编程中,模块A可能直接引用模块B和模块C的具体实现,这样的话如果需要修改模块B或模块C的实现,就会牵一发而动全身,系统的可维护性会大大降低。而通过面向接口编程,我们可以定义接口IStrategy来描述模块B和模块C的通信规范,模块A只需要依赖于接口IStrategy而不是具体的实现类,这样一来,修改模块B或模块C的实现只需要修改具体的实现类,不会影响到模块A,这就体现了依赖倒置的思想
工作中的案例:
MVC三层架构中,Controller层会依赖Service层的接口,而不直接依赖Service层的实现类,这就是面向接口编码,依赖于抽象而不依赖于具体实现。一开始不理解为什么要多出来这么一个接口类,参考我们在Service层里面也是调用Mapper层的接口,不依赖Mapper层的具体的实现,这样当底层的数据源切换的时候,不会影响到service层的代码。(高层代码不依赖低层代码,只依赖于抽象)
RedissonClient,在实际使用中,不会把他注入到各个类中,而是定义一个redis的接口,统一定义接口方法,并且实现这些方法。在实际使用的时候通过注入IRedisService 接口来使用Redisson,这样就屏蔽了底层的具体实现。
接口:
public interface IRedisService {
/**
* 设置指定 key 的值
*
* @param key 键
* @param value 值
*/
<T> void setValue(String key, T value);
}
实现类:
@Service("redissonService")
public class RedissonService implements IRedisService {
@Resource
private RedissonClient redissonClient;
public <T> void setValue(String key, T value) {
redissonClient.<T>getBucket(key).set(value);
}
@Override
public <T> void setValue(String key, T value, long expired) {
RBucket<T> bucket = redissonClient.getBucket(key);
bucket.set(value, Duration.ofMillis(expired));
}
}
短信发送功能
在一个通知系统中,可能需要通过不同的方式(如邮件、短信、推送等)发送消息。通过定义一个抽象的消息发送接口,高层模块可以依赖于这个接口,而不是具体的消息发送实现。这样,当需要添加新的消息发送方式时,只需实现一个新的消息发送类,而无需修改高层模块的代码。
(在高层模块,具体使用哪个实现类的方法,可以通过工厂模式,配置文件等的方式来实现)