依赖倒置原则(DIP)

深入理解依赖倒置原则

依赖倒置原则不仅仅是关于接口和实现的分离,它更是一种架构设计哲学,主要包括:

  • 控制反转:依赖关系的控制权从高层模块转移到外部容器
  • 抽象稳定性:抽象比具体实现更稳定,基于抽象的设计更能适应变化
  • 框架设计:DIP是许多现代框架(如Spring)的核心理论基础

Java示例

违反DIP的示例

java 复制代码
// 低层模块 - 具体实现
class EmailService {
    public void sendEmail(String message) {
        System.out.println("发送邮件: " + message);
    }
}

class SMSService {
    public void sendSMS(String message) {
        System.out.println("发送短信: " + message);
    }
}

// 高层模块 - 直接依赖具体实现
class Notification {
    private EmailService emailService;
    private SMSService smsService;
    
    public Notification() {
        this.emailService = new EmailService(); // 紧耦合
        this.smsService = new SMSService();     // 紧耦合
    }
    
    public void notifyByEmail(String message) {
        emailService.sendEmail(message);
    }
    
    public void notifyBySMS(String message) {
        smsService.sendSMS(message);
    }
}

问题分析:

  • Notification 类直接依赖于具体实现
  • 难以测试(无法mock依赖)
  • 添加新通知方式需要修改 Notification

遵循DIP的示例

java 复制代码
// 步骤1: 定义抽象层
interface MessageService {
    void sendMessage(String message);
}

// 步骤2: 具体实现依赖于抽象
class EmailService implements MessageService {
    @Override
    public void sendMessage(String message) {
        System.out.println("发送邮件: " + message);
    }
}

class SMSService implements MessageService {
    @Override
    public void sendMessage(String message) {
        System.out.println("发送短信: " + message);
    }
}

class WeChatService implements MessageService {
    @Override
    public void sendMessage(String message) {
        System.out.println("发送微信: " + message);
    }
}

// 步骤3: 高层模块依赖于抽象
class Notification {
    private MessageService messageService;
    
    // 通过构造器注入依赖
    public Notification(MessageService messageService) {
        this.messageService = messageService;
    }
    
    public void notifyUser(String message) {
        messageService.sendMessage(message);
    }
    
    // 通过setter注入依赖
    public void setMessageService(MessageService messageService) {
        this.messageService = messageService;
    }
}

使用示例

java 复制代码
public class DIPDemo {
    public static void main(String[] args) {
        // 创建具体服务
        MessageService emailService = new EmailService();
        MessageService smsService = new SMSService();
        MessageService wechatService = new WeChatService();
        
        // 通过依赖注入使用不同的服务
        Notification emailNotification = new Notification(emailService);
        emailNotification.notifyUser("这是一封重要邮件");
        
        Notification smsNotification = new Notification(smsService);
        smsNotification.notifyUser("这是一条紧急短信");
        
        // 动态切换服务
        Notification notification = new Notification(emailService);
        notification.notifyUser("第一条消息通过邮件发送");
        
        notification.setMessageService(wechatService);
        notification.notifyUser("第二条消息通过微信发送");
    }
}

更复杂的示例 - 订单处理系统

java 复制代码
// 抽象层
interface PaymentProcessor {
    boolean processPayment(double amount);
}

interface OrderRepository {
    void save(Order order);
}

interface NotificationService {
    void sendOrderConfirmation(Order order);
}

// 具体实现
class CreditCardProcessor implements PaymentProcessor {
    @Override
    public boolean processPayment(double amount) {
        System.out.println("信用卡支付: $" + amount);
        return true;
    }
}

class PayPalProcessor implements PaymentProcessor {
    @Override
    public boolean processPayment(double amount) {
        System.out.println("PayPal支付: $" + amount);
        return true;
    }
}

class DatabaseOrderRepository implements OrderRepository {
    @Override
    public void save(Order order) {
        System.out.println("订单保存到数据库: " + order.getId());
    }
}

class EmailNotificationService implements NotificationService {
    @Override
    public void sendOrderConfirmation(Order order) {
        System.out.println("发送订单确认邮件: " + order.getId());
    }
}

// 订单类
class Order {
    private String id;
    private double amount;
    
    public Order(String id, double amount) {
        this.id = id;
        this.amount = amount;
    }
    
    // getters...
    public String getId() { return id; }
    public double getAmount() { return amount; }
}

// 高层模块 - 订单服务
class OrderService {
    private PaymentProcessor paymentProcessor;
    private OrderRepository orderRepository;
    private NotificationService notificationService;
    
    // 依赖注入
    public OrderService(PaymentProcessor paymentProcessor, 
                       OrderRepository orderRepository,
                       NotificationService notificationService) {
        this.paymentProcessor = paymentProcessor;
        this.orderRepository = orderRepository;
        this.notificationService = notificationService;
    }
    
    public boolean processOrder(Order order) {
        // 处理支付
        boolean paymentSuccess = paymentProcessor.processPayment(order.getAmount());
        if (!paymentSuccess) {
            return false;
        }
        
        // 保存订单
        orderRepository.save(order);
        
        // 发送通知
        notificationService.sendOrderConfirmation(order);
        
        return true;
    }
}

// 使用示例
public class OrderSystemDemo {
    public static void main(String[] args) {
        // 创建依赖
        PaymentProcessor paymentProcessor = new PayPalProcessor();
        OrderRepository orderRepository = new DatabaseOrderRepository();
        NotificationService notificationService = new EmailNotificationService();
        
        // 注入依赖
        OrderService orderService = new OrderService(
            paymentProcessor, orderRepository, notificationService
        );
        
        // 处理订单
        Order order = new Order("ORDER123", 99.99);
        boolean success = orderService.processOrder(order);
        System.out.println("订单处理" + (success ? "成功" : "失败"));
    }
}

高级使用

依赖注入容器模拟

java 复制代码
// 简单的依赖注入容器
class DIContainer {
    private final Map<Class<?>, Object> instances = new ConcurrentHashMap<>();
    private final Map<Class<?>, Class<?>> implementations = new ConcurrentHashMap<>();
    
    public <T> void register(Class<T> interfaceType, Class<? extends T> implementation) {
        implementations.put(interfaceType, implementation);
    }
    
    public <T> void registerInstance(Class<T> interfaceType, T instance) {
        instances.put(interfaceType, instance);
    }
    
    @SuppressWarnings("unchecked")
    public <T> T resolve(Class<T> interfaceType) {
        // 首先检查是否有现有实例
        T instance = (T) instances.get(interfaceType);
        if (instance != null) {
            return instance;
        }
        
        // 创建新实例
        Class<?> implementation = implementations.get(interfaceType);
        if (implementation == null) {
            throw new RuntimeException("No implementation registered for: " + interfaceType);
        }
        
        try {
            instance = (T) implementation.getDeclaredConstructor().newInstance();
            instances.put(interfaceType, instance);
            return instance;
        } catch (Exception e) {
            throw new RuntimeException("Failed to create instance of: " + implementation, e);
        }
    }
}

// 使用依赖注入容器
class DIPWithContainerDemo {
    public static void main(String[] args) {
        DIContainer container = new DIContainer();
        
        // 注册依赖
        container.register(MessageSender.class, EmailSender.class);
        container.register(MessageFilter.class, SensitiveWordFilter.class);
        container.register(SendStatusListener.class, LoggingStatusListener.class);
        
        // 解析使用
        MessageSender sender = container.resolve(MessageSender.class);
        MessageFilter filter = container.resolve(MessageFilter.class);
        
        System.out.println("通过DI容器解析的实例: " + sender.getClass().getSimpleName());
    }
}

配置化系统

java 复制代码
// 基于配置的发送器工厂
class MessageSenderFactory {
    private final Properties config;
    
    public MessageSenderFactory(Properties config) {
        this.config = config;
    }
    
    public List<MessageSender> createSenders() {
        List<MessageSender> senders = new ArrayList<>();
        
        if ("true".equals(config.getProperty("email.enabled"))) {
            senders.add(new EmailSender(
                config.getProperty("email.smtp.server"),
                config.getProperty("email.username"), 
                config.getProperty("email.password")
            ));
        }
        
        if ("true".equals(config.getProperty("sms.enabled"))) {
            senders.add(new SMSSender(
                config.getProperty("sms.api.key"),
                config.getProperty("sms.api.secret")
            ));
        }
        
        // 可以继续添加其他发送器...
        
        return senders;
    }
}

优点

  1. 完全解耦 :高层模块 MessageDispatcher 不依赖任何具体实现
  2. 易于测试:所有依赖都可以被mock
  3. 运行时扩展:可以动态添加新的发送器、过滤器、监听器
  4. 配置灵活:通过配置决定使用哪些组件
  5. 便于扩展:新功能可以通过实现接口轻松添加
相关推荐
Haooog2 小时前
654.最大二叉树(二叉树算法)
java·数据结构·算法·leetcode·二叉树
东方芷兰3 小时前
JavaWeb 课堂笔记 —— 20 SpringBootWeb案例 配置文件
java·开发语言·笔记·算法·log4j·intellij-idea·lua
Roye_ack3 小时前
【项目实战 Day9】springboot + vue 苍穹外卖系统(用户端订单模块 + 商家端订单管理模块 完结)
java·vue.js·spring boot·后端·mybatis
人间有清欢3 小时前
java数据权限过滤
java·mybatis·权限控制·数据过滤
A阳俊yi3 小时前
Spring——声明式事务
java·数据库·spring
我要精通C++3 小时前
lua虚拟机的垃圾回收机制
java·开发语言
22jimmy3 小时前
MyBatis动态sql
java·开发语言·mybatis
那我掉的头发算什么4 小时前
【数据结构】双向链表
java·开发语言·数据结构·链表·intellij-idea·idea
半桔4 小时前
【STL源码剖析】从源码看 list:从迭代器到算法
java·数据结构·c++·算法·stl·list