依赖倒置原则(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. 便于扩展:新功能可以通过实现接口轻松添加
相关推荐
青衫码上行7 小时前
【Java Web学习 | 第1篇】前端 - HTML
java·前端·学习
周杰伦_Jay7 小时前
【常用设计模式全解析】创建型模式(聚焦对象创建机制)、结构型模式(优化类与对象的组合关系)、行为型模式(规范对象间的交互行为)
设计模式·架构·开源·交互·1024程序员节
阿金要当大魔王~~7 小时前
uniapp img 动态渲染 的几种用法
java·服务器·前端·1024程序员节
摸鱼的老谭7 小时前
Java 25 中的最佳新特性
java·1024程序员节
lang201509288 小时前
Spring Boot健康检查全解析
java·spring boot·后端
我是华为OD~HR~栗栗呀8 小时前
华为OD-Java面经-21届考研
java·c++·后端·python·华为od·华为·面试
考虑考虑9 小时前
流收集器
java·后端·java ee
今天背单词了吗9809 小时前
Spring Boot+RabbitMQ 实战:4 种交换机模式(Work/Fanout/Direct/Topic)保姆级实现
java·spring·中间件·rabbitmq·1024程序员节
九皇叔叔9 小时前
Java循环结构全解析:从基础用法到性能优化
java·开发语言·性能优化
流星5211229 小时前
GC 如何判断对象该回收?从可达性分析到回收时机的关键逻辑
java·jvm·笔记·学习·算法