Каковы некоторые рекомендации по созданию конструктора, который принимает логическое значение isX и в зависимости от этого значения может потребовать логическое значение для isY?

В этой гипотетической задаче я создаю класс для представления колбасы, который может быть: A. Свежий и упакованный B. Свежий и неупакованный C. Не свежие и не упакованные

Примечание: он не может быть не свежим и не упакованным.

Я ищу лучшую практику для создания конструктора с учетом этого.

Способ, которым я пытался, приведен ниже, но я думаю, что должны быть лучшие решения.

public class Sausage {
    Meat meat;
    boolean isFresh;
    boolean isPackaged;

    public Sausage(Meat meat, Boolean isFresh, Boolean isPackaged) {
        this.meat = meat;
        if (!isFresh) {
            this.isFresh = false;
            this.isPackaged = false;
        }
        else if (isPackaged) {
            this.isFresh = true;
            this.isPackaged = true;
        }
        else {
            this.isFresh = true;
            this.isPackaged = false;
        }
    }
}

Я ищу более чистый способ обеспечить эту функциональность.

По какой причине вы используете объекты Boolean в качестве параметра вместо их примитивного аналога (который вы используете внутри)?

second 29.05.2019 02:01
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
1
75
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Есть несколько проблем с вашим текущим подходом:

  1. Существует способ создать объект записи new, который не имеет смысла, например. new Sausage(..., false, true), где упаковано, будет автоматически преобразовано в false. Это сбивает с толку и затрудняет понимание кода.

  2. Вы смешиваете Boolean тип объекта и boolean примитивный тип, что приводит к ненужной автоматической упаковке. Если вам не нужно поддерживать null, используйте boolean.

  3. boolean поля, вероятно, не нуждаются в префиксе is.

Поскольку есть два логических флага и 4 возможности, которые они могут быть установлены (true true, true false, false true, false false), но только 3 допустимых варианта, возможно, с именами фабричных методов были бы более подходящими:

public class Sausage {

    public static Sasuage newFreshPackaged(Meat meat) {
      return new Sasuage(meat, true, true);
    }

    public static Sasuage newFreshNotPackaged(Meat meat) {
      return new Sasuage(meat, true, false);
    }

    public static Sasuage newNotFreshNotPackaged(Meat meat) {
      return new Sasuage(meat, false, false);
    }

    private Sausage(Meat meat, boolean fresh, boolean packaged) {
        this.meat = meat;
        this.fresh = fresh;
        this.packaged = packaged;
    }
}

Автоматическое изменение isPackaged на false может стать неожиданностью для вызывающего кода. Здесь вы можете выбрать исключение, если выбрана комбинация (не свежая, упакованная).

if (!isFresh && isPackaged) {
    throw new IllegalArgumentException("Can't be both not fresh and packaged!");
}
this.isFresh = isFresh;
this.isPackaged = isPackaged;

Вы также можете решить использовать фабричные методы (создав свой конструктор private), которые обеспечивают выполнение ваших требований. Это позволит избежать необходимости создания исключения.

public static Sausage createFreshSausage(Meat meat, boolean isPackaged) {
    return new Sausage(meat, true, isPackaged);
}

public static Sausage createNotFreshSausage(Meat meat) {
    return new Sausage(meat, false, false);
}

Между прочим, обычно примитив boolean будет использоваться в типах параметров конструктора, а не в оболочке объекта Boolean, как ваши переменные экземпляра. Значение null, которое было бы разрешено Boolean, не имеет никакого смысла.

Ответ принят как подходящий

Вы можете представить возможные состояния как тип перечисления:

enum SausageType {
    FreshPackaged,
    FreshUnpackaged,
    NotFresh;
}

Затем измените свой конструктор, чтобы он принимал SausageType вместо двух Boolean.

Преимущество этого метода в том, что невозможно вызвать конструктор с неправильной комбинацией состояний, пользователям вашего класса очевидно, каковы возможные значения, и вам не нужно помнить о хрупкой проверке аргументов во время выполнения. в курсе меняющихся требований.

Отлично. Проблема ОП на самом деле не в том, чтобы «обработать все варианты всех различных логических условий». На самом деле это «определение« состояния »». Таким образом, перечисление является решением ИДЕАЛ.

paulsm4 29.05.2019 01:09

@ paulsm4: идеальность решения зависит от того, как будет использоваться остальная часть кода. Поскольку это теоретический вопрос, давайте предположим сценарий, в котором вы получаете свежее и упакованное состояние откуда-то еще (например, из некоторых внешних служб). В этом случае вам все равно понадобится фабрика для преобразования различных флагов в перечисление, поэтому может быть более подходящим использовать фабрику в первую очередь.

second 29.05.2019 02:00

@second Совершенно верно - общая применимость моего ответа будет зависеть от того, как выглядит остальная часть кода.

Brennan Vincent 29.05.2019 07:26

во-вторых, утверждается, что рассмотрение «enum» в качестве решения может быть преждевременным, если вы не знаете больше о приложении. Я не могу не согласиться. Но болтать о "фабриках" еще БОЛЕЕ "преждевременно" по той же причине. Я просто боялся, что ОП может быть «заблокирован» и думать исключительно о логических значениях и блоках if/else. Альтернативная точка зрения Браннана Винсента - рассмотрение "состояния" вместо "жонглирования булевыми значениями" была чрезвычайно полезной. ПО МОЕМУ МНЕНИЮ :)

paulsm4 29.05.2019 18:08

Спасибо за это решение. Прочитав ваши комментарии, это будет решение, которое я реализую. Я обобщил проблему, однако контекст создает библиотеку, поэтому это решение прекрасно работает. Я не был знаком с enum. Спасибо вам всем.

iicsa 29.05.2019 19:27

Другие вопросы по теме