Я бы использовал второй, где это возможно, вставляя зависимости классов, возьмите этот пример, где конструктору Tea
требуется больше информации:
class Mug {
private Tea tea;
public Mug(int temperature) {
this.tea = new Tea(temperature);
}
public boolean isFull() {
return tea.value != 10;
}
}
Посмотрите, как ужасно, что конструктору Mug
теперь требуется информация, используемая только конструктором Tea
.
Но, как бы там ни было, я бы сказал, что ни один из ваших примеров не нарушает принципа SOLID.
Ничто не говорит о том, что вы не можете создать новый объект внутри другого, и ничего, что говорит о том, что вы должны создавать абстракции.
Здесь было бы реальное нарушение в этой области:
class Mug { // VIOLATION
private Tea tea;
private Coffee coffee;
public Mug(boolean tea) {
if (tea) {
this.tea = new Tea();
} else {
this.coffee = new Coffee();
}
}
public boolean isFull() {
return tea.value != 10 || coffee.value != 10;
}
}
Класс зависит от нескольких похожих классов. Сравните с:
class Mug {
private Liquid liquid;
public Mug(Liquid liquid) {
this.liquid = liquid;
}
public boolean isFull() {
return liquid.getVolume() != 10;
}
}
interface Liquid {
int getVolume();
}
class Tea implements Liquid {
private int volume;
@Override
public int getVolume() {
return volume;
}
}
class Coffee implements Liquid {
private int volume;
@Override
public int getVolume() {
return volume;
}
}
Но поскольку у вас есть только одна вещь, которая может войти в Mug
, здесь нет нарушения и нет необходимости в абстракции. В общем, никогда не пишите код, который не решает проблему.
И никогда не создавайте абстракцию с таким именем, как ITea
. В таком случае либо конкретное имя класса недостаточно конкретное, либо имя абстракции недостаточно общее.