Создать экземпляр в классе или получить объект извне, что на true? - PullRequest
0 голосов
/ 11 мая 2018

Я изучил принцип SOLID и создал для меня вопрос об этом. вы предполагаете, что нам нужен Tea объект в Mug классе, теперь это лучше, чем создание экземпляра из Tea в Mug классе или передача извне через Constructor или setter метод.

что на истине?

пример:

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 объект в нашей программе.

Ответы [ 2 ]

0 голосов
/ 12 мая 2018

Я бы использовал второй, где это возможно, вставляя зависимости классов, возьмите этот пример, где конструктору 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. В таком случае либо конкретное имя класса недостаточно конкретное, либо имя абстракции недостаточно общее.

0 голосов
/ 11 мая 2018

Оба ваших дела нарушают SOLID.

Каждая ваша конкретная реализация (конкретный класс) должна зависеть только от абстракций. в твоем случае чай это не абстракция. Кружка имеет крепкую связь с чаем. Ниже приведен возможный способ его кодирования.

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.
 }

EDIT: 1. Если мы уверены, что есть только одна возможная реализация чая. Кроме того, интерфейс лучше, так как конкретные реализации трудно подделать и, следовательно, затрудняет юнит-тестирование.

  1. Избегайте использования перечислений для установки типа. Перечисляет случаи внедрения переключателя и в будущем, если добавляется случай, необходимо изменить все такие случаи переключения, что приведет к нарушению O в SOLID.

Если кейс добавлен, вам нужно изменить существующий код, а если вы забудете добавить кейс, это приведет к непредвиденным ошибкам. (Это нарушает OCP. Вместо перечислений ставить логику в конкретную реализацию, иметь общий интерфейс и конкретную реализацию). Также, если мы реализуем логику, специфичную для конкретного случая, в отдельных экземплярах enum, то файл enum станет гигантским. Вместо этого, если у нас есть конкретная логика в отдельных конкретных классах, реализация общего интерфейса упрощает пользовательский код, поскольку он может быть внедрен в конкретные классы полиморфным способом.

p.s. Этот ответ о следовании принципам, и это не всегда возможно сделать. Хорошо нарушать принцип, но мы должны знать, что мы его нарушаем, и у нас есть очень веские основания для этого .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...