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

采用构造函数依赖注入后Main方法臃肿,求优化方案

嘿,我太懂这种糟心的情况了——把所有对象构建逻辑都堆在main方法里,瞬间就变成一团乱糟糟的“初始化面条代码”,后续维护起来简直头疼。既然你已经用构造函数实现了规范的依赖注入,那核心思路就是把对象组装的职责从main里抽离出来,给你几个适配你场景的实用方案:

方案1:用工厂类封装组装逻辑

最直接的方式是创建一个专门的工厂类,把所有对象的组装逻辑都放到这里,让main只负责启动应用。比如针对你的代码,我们可以写一个AppFactory:

public class AppFactory {
    // 对外暴露创建MyApp的入口方法
    public static MyApp createMyApp() {
        // 从底层依赖开始构建,按依赖顺序来
        Config config = Config.getInstance(); // 假设Config是单例或全局可获取
        CustomChart customChart = new CustomChart(config.getChartOptionOne(), config.getChartOptionTwo());
        
        // 构建子视图
        MyModel model = getMyModel();
        SubView subView1 = new SubView(model);
        SubView subView2 = new SubView(model, customChart);
        
        // 构建主视图和最终的MyApp
        View view = new View(subView1, subView2);
        return new MyApp(model, view);
    }
    
    // 把模型读取的逻辑单独抽出来,方便复用或修改
    private static MyModel getMyModel() {
        return MyModelFileReader.getModel(Config.getDefaultFile());
    }
}

然后你的main方法就会变得无比清爽:

public static void main(String[] args) {
    MyApp myApp = AppFactory.createMyApp();
    myApp.start();
}

这个方案的好处是:

  • 把复杂的组装逻辑封装起来,main保持“启动器”的单一职责
  • 工厂里的方法可以单独编写单元测试,依赖变化时只需要修改工厂类
  • 后续如果需要不同配置的MyApp,只需要在工厂里加个createMyAppWithCustomConfig()方法就行

方案2:用依赖注入容器管理依赖(适合中大型项目)

如果你的项目后续会变得更复杂,依赖关系越来越多,那直接用DI容器会更省心——不管是Spring、Guice这类成熟框架,还是自己手写一个简单的容器,都能帮你自动管理对象的创建和依赖注入。

举个手写简易DI容器的例子:

public class SimpleDIContainer {
    private final Map<Class<?>, Object> singletonInstances = new HashMap<>();
    // 用名称区分同类型不同实例的情况,比如两个SubView
    private final Map<String, Object> namedInstances = new HashMap<>();

    public void init() {
        // 按依赖顺序注册所有对象
        registerSingleton(Config.class, Config.getInstance());
        
        MyModel model = MyModelFileReader.getModel(getInstance(Config.class).getDefaultFile());
        registerSingleton(MyModel.class, model);
        
        CustomChart chart = new CustomChart(getInstance(Config.class).getChartOptionOne(), getInstance(Config.class).getChartOptionTwo());
        registerSingleton(CustomChart.class, chart);
        
        // 注册第一个SubView
        registerSingleton(SubView.class, new SubView(getInstance(MyModel.class)));
        // 注册带Chart的SubView,用名称标识
        registerNamed("subViewWithChart", new SubView(getInstance(MyModel.class), getInstance(CustomChart.class)));
        
        View view = new View(getInstance(SubView.class), (SubView) getNamed("subViewWithChart"));
        registerSingleton(View.class, view);
        
        registerSingleton(MyApp.class, new MyApp(getInstance(MyModel.class), getInstance(View.class)));
    }

    // 省略注册、获取实例的工具方法实现...
}

main方法里只需要初始化容器并获取实例:

public static void main(String[] args) {
    SimpleDIContainer container = new SimpleDIContainer();
    container.init();
    MyApp myApp = container.getInstance(MyApp.class);
    myApp.start();
}

这个方案适合依赖复杂的场景,能帮你省去手动组装的麻烦,还能轻松实现单例、原型等对象生命周期管理。

方案3:用构建器模式优化对象创建(适合参数多的对象)

如果MyApp或者View这类核心对象的构造参数特别多,用构建器模式能让代码可读性更强,还能灵活组合不同的依赖配置。比如给MyApp写一个构建器:

public class MyAppBuilder {
    private MyModel myModel;
    private View view;

    // 提供设置依赖的方法,链式调用更清爽
    public MyAppBuilder withModel(MyModel model) {
        this.myModel = model;
        return this;
    }

    public MyAppBuilder withView(View view) {
        this.view = view;
        return this;
    }

    // 提供默认依赖的快捷方法,减少外部代码的复杂度
    public MyAppBuilder withDefaultModel() {
        this.myModel = MyModelFileReader.getModel(Config.getDefaultFile());
        return this;
    }

    public MyAppBuilder withDefaultView() {
        if (myModel == null) {
            throw new IllegalStateException("请先设置Model");
        }
        Config config = Config.getInstance();
        CustomChart chart = new CustomChart(config.getChartOptionOne(), config.getChartOptionTwo());
        this.view = new View(new SubView(myModel), new SubView(myModel, chart));
        return this;
    }

    // 构建最终对象,还可以加参数校验
    public MyApp build() {
        if (myModel == null || view == null) {
            throw new IllegalArgumentException("Model和View不能为空");
        }
        return new MyApp(myModel, view);
    }
}

main方法里的代码就会变得非常直观:

public static void main(String[] args) {
    MyApp myApp = new MyAppBuilder()
            .withDefaultModel()
            .withDefaultView()
            .build();
    myApp.start();
}

这个方案的优势是代码可读性极强,而且如果后续需要自定义某个依赖(比如用测试用的Model),只需要调用withModel(testModel)就行,非常灵活。


总的来说,核心原则就是让main方法只做“启动应用”这一件事,把对象组装的脏活累活交给专门的组件去处理。如果是小项目,工厂模式足够;中大型项目可以考虑DI容器;如果对象参数多,构建器模式会更友好。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 08:32:48