You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在不违反依赖注入原则的前提下创建含其他类实例列表的类?

如何在遵循依赖注入原则的前提下实现Foo实例管理类

嘿,针对你的问题,咱们可以通过依赖倒置+构造函数注入的方式来实现,完全符合依赖注入原则,同时还能让代码更灵活、易测试。下面一步步来拆解:

核心思路:解耦职责

依赖注入的核心是依赖抽象而非具体实现,并且把对象的创建控制权交给外部。咱们要把「从CSV读取数据创建Foo」和「管理Foo列表做计算」这两个职责分开:

  • 管理类只负责业务计算,不关心数据从哪来
  • 专门的组件负责数据读取和Foo实例化,管理类依赖这个组件的抽象接口

第一步:抽象数据提供的接口

先定义一个抽象接口,用来规范「提供Foo实例列表」的行为,这样管理类只需要依赖这个接口,不用管具体是从CSV还是别的地方来的数据:

import java.util.List;

public interface FooDataProvider {
    List<Foo> provideFoos();
}

第二步:实现CSV版的数据提供者

把原来要放在管理类里的CSV读取、解析逻辑,单独抽成一个实现类,专门负责从CSV文件生成Foo列表:

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class CsvFooDataProvider implements FooDataProvider {
    private final String csvFilePath;

    // 这里可以根据需要注入其他依赖,比如CSV解析库的实例,保持灵活性
    public CsvFooDataProvider(String csvFilePath) {
        this.csvFilePath = csvFilePath;
    }

    @Override
    public List<Foo> provideFoos() {
        List<Foo> fooList = new ArrayList<>();
        try (BufferedReader br = new BufferedReader(new FileReader(csvFilePath))) {
            String line;
            // 跳过表头(如果你的CSV有表头的话,没有可以删掉这行)
            br.readLine();
            while ((line = br.readLine()) != null) {
                String[] args = line.split(",");
                fooList.add(new Foo(args));
            }
        } catch (IOException e) {
            // 这里可以根据业务需求处理异常,比如封装成自定义异常抛出
            throw new RuntimeException("Failed to load Foo data from CSV", e);
        }
        return fooList;
    }
}

第三步:实现依赖注入的管理类

管理类通过构造函数注入FooDataProvider接口,在初始化时获取Foo列表,之后专注于业务计算:

import java.util.List;

public class FooManager {
    private final List<Foo> fooList;

    // 构造函数注入依赖,这是最推荐的DI方式(强制依赖,不可为空)
    public FooManager(FooDataProvider dataProvider) {
        this.fooList = dataProvider.provideFoos();
    }

    // 示例计算方法,你可以替换成自己的业务逻辑
    public int calculateSumOfFirstCoef() {
        return fooList.stream().mapToInt(Foo::getFirstCoef).sum();
    }

    // 其他业务方法...
}

第四步:组装依赖并使用

在应用的入口(比如main方法)或者配置类里,创建具体的数据提供者实例,注入给管理类:

public class Main {
    public static void main(String[] args) {
        // 创建具体的CSV数据提供者
        FooDataProvider csvProvider = new CsvFooDataProvider("your/file/path/data.csv");
        // 注入依赖创建管理类实例
        FooManager fooManager = new FooManager(csvProvider);
        
        // 调用管理类的业务方法
        int total = fooManager.calculateSumOfFirstCoef();
        System.out.println("Total of first coefficients: " + total);
    }
}

为什么这符合依赖注入原则?

  • 依赖倒置:FooManager依赖的是抽象的FooDataProvider,而不是具体的CsvFooDataProvider。以后如果要从数据库、API或者内存读取Foo数据,只需要新增一个FooDataProvider的实现类,完全不用修改FooManager的代码。
  • 控制反转:创建Foo列表的控制权从FooManager转移到了外部的提供者类,FooManager只需要专注于业务计算,不用关心数据来源和解析细节。
  • 可测试性:单元测试时,你可以写一个MockFooDataProvider,返回预设的Foo列表,不用依赖真实的CSV文件,测试起来更简单。

内容的提问来源于stack exchange,提问作者Elena Heinsalu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 04:15:12