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

基于SOLID原则:Mug类中Tea对象的创建方式哪种更优?

哪种Mug类实现更符合SOLID设计原则?

假设我们的程序中Mug类仅支持Tea对象,那么是在Mug类内部构造函数中实例化Tea对象更好,还是通过构造器或setter方法从外部传入Tea实例更好?

以下为两种实现示例:

第一种实现(内部实例化Tea):

class Mug {
    private Tea tea;
    public Mug(){
        this.tea = new Tea();
    }
    public boolean isFull(){
        return this.tea.value != 10;
    }
}

第二种实现(外部传入Tea):

class Mug {
    private Tea tea;
    public Mug(Tea tea){
        this.tea = tea;
    }
    // public void setTea(Tea tea){
    //     this.tea = tea;
    // }
    public boolean isFull(){
        return this.tea.value != 10;
    }
}

调用示例:

public class Test {
    static void main(String[] args){
        Mug mug = new Mug(); // 第一种实现的调用方式
        // or
        Mug mug = new Mug(new Tea()); // 第二种实现的调用方式
    }
}

请问哪种实现方式更优?


毫无疑问第二种实现方式更优,完全贴合SOLID原则的核心思想,尤其是依赖倒置原则,我们来拆解下原因:

  • 依赖倒置原则(DIP):高层模块(Mug)不应该依赖低层模块(Tea)的具体实现,而是依赖抽象。虽然这里Tea是具体类,但通过外部传入的方式,Mug不再负责Tea的创建,它只需要知道自己依赖Tea这个类型即可。如果未来Tea需要修改构造逻辑(比如需要传入参数new Tea("green")),第一种实现需要修改Mug的构造函数,而第二种只需要在调用方调整,完全符合开闭原则(对扩展开放,对修改关闭)。

  • 单一职责原则(SRP):Mug的职责应该是“容纳Tea并判断是否满”,而不是“创建Tea”。第一种实现让Mug承担了额外的对象创建职责,违反了单一职责,当Tea的创建逻辑变化时,Mug也得跟着改,维护成本更高。

  • 可测试性:如果要测试Mug的isFull方法,第二种实现可以传入一个Mock的Tea对象(比如设置value为10或者其他值),而第一种实现只能依赖Tea的真实构造,测试灵活性大大降低。

这里额外提一下注释里的setter方法:如果业务逻辑允许Mug中途更换Tea,那保留setter是合理的;但如果Mug一旦创建就应该绑定固定的Tea,那只保留构造注入就足够了,避免不必要的状态变化。

总结下来,第二种实现把对象创建的职责交给了上层调用者,让Mug只专注于自己的核心功能,无论是扩展性、维护性还是可测试性都远优于第一种。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:19:19