首页 > 解决方案 > 在类中创建实例或从外部获取对象,哪个是正确的?

问题描述

我研究了SOLID原理并为我提出了一个关于它的问题。你假设我们需要一个类中的Tea对象Mug,现在这比从类Tea中创建一个实例Mug或从外部通过Constructororsetter方法传递更好。

哪个是真的?

例子:

class Mug {

    private Tea tea;

    public Mug(){
       this.tea = new Tea();
    }

    public boolean isFull(){
       return this.tea.value != 10;
    }
}

或者

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.team.value != 10;
    }
}

利用:

  public class Test {

   static void main(String[] args){
       Mug mug = new Mug();
       //or
       Mug mug = new Mug(new Tea());
  }
}

哪一个更好?

注意:假设在我们的程序中Mug只支持Tea对象。

标签: javaoopsolid-principles

解决方案


你的两个案例都违反了 SOLID。

您的每个具体实现(具体类)应该只依赖于抽象。在您的情况下,茶不是抽象的。Mug 与 Tea 紧密耦合。下面是一种可能的编码方式。

public interface ITea{
     //tea related methods which you think should be exposed to outside world. Also all implementation of ITea must support these method (L in SOLID)
 }

public class Tea implements ITea{
  // Implement the contract methods from ITea
}

public class Mug {
    private ITea tea;
    // Have constructor or setter to inject concrete implementation. Setter will provide you capability to modify behavioral at run time.
 }

编辑: 1. 如果我们确定只有一种可能的茶实现。然后接口也更好,因为具体实现很难模拟,因此单元测试很困难。

  1. 避免使用枚举来设置类型。枚举注入 switch 案例,并且将来如果添加一个案例,所有这些 switch 案例都需要修改,从而导致违反 SOLID 中的 O。

如果添加案例,您必须修改现有代码,如果您忘记在某处添加案例,则会导致意外错误。(它违反了OCP。而不是枚举将逻辑放在特定的实现中,具有通用的接口和特定的实现)。此外,如果我们在枚举的各个实例中实现特定于案例的逻辑,那么枚举文件将变得巨大。相反,如果我们在实现公共接口的各个具体类中具有特定逻辑,则用户代码可以很容易,因为它可以以多态方式注入具体类。

ps这个答案是关于遵循原则的,并不总是可以这样做。违反原则是可以的,但我们必须知道我们正在违反它,并且有充分的理由这样做


推荐阅读