У меня есть класс Transaction, который выглядит так:

public class Transaction {

  private Transaction parentTransaction;
  private long amount;
  private String orderNumber;
}

Таким образом, у него есть поле, которое указывает на другой Transaction.

Есть еще такой метод:

public void build(Transaction transaction) {
    final long amount = transaction.getParentTransaction() == null ? transaction.getAmount() : transaction.getParentTransaction().getAmount();
    final String orderNumber = transaction.getParentTransaction() == null ? transaction.getOrderNumber() : transaction.getParentTransaction().getOrderNumber();
    // same pattern follows for more fields...


    // do other stuff...
}

В зависимости от того, существует ли parentTransaction, например. поле amount должно использоваться из parentTransaction или transaction. Что мне не нравится в этом подходе, так это повторяющееся использование термина transaction.getParentTransaction() == null ? ....

Есть ли какой-то шаблон или подход, как я мог этого избежать?

1
Robert Strauch 18 Янв 2022 в 15:11
Может быть, Optional может помочь? Там хорошие операторы.
 – 
Barracuda
18 Янв 2022 в 15:12
Использовать необязательно?
 – 
Shawn
18 Янв 2022 в 15:13
1
Просто сделайте if(transaction.getParentTransaction() != null) transaction = transaction.getParentTransaction(); в самом начале.
 – 
Holger
18 Янв 2022 в 15:24

4 ответа

Лучший ответ

Попробуйте Необязательно, как было предложено другими:

public void build(Transaction transaction) {
        
        Transaction parentTransactionElseTransaction = Optional.of(transaction)
                .map(t -> t.getParentTransaction())
                .orElse(transaction);

        final long amount = parentTransactionElseTransaction.getAmount();
        final String orderNumber = parentTransactionElseTransaction.getOrderNumber();

        // same pattern follows for more fields...
        // do other stuff...
    }
2
indybee 18 Янв 2022 в 15:22

Необязательный вариант, но я думаю, что есть гораздо более простое решение:

public void build(Transaction transaction) {
    Transaction buildFrom = transaction.getParentTransaction() == null ? transaction : transaction.getParentTransaction();
    ...
    String orderNumber = buildFrom.getOrderNumber();

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

3
GhostCat 18 Янв 2022 в 15:29
2
Этот вспомогательный метод уже существует (JDK 9+): Transaction buildFrom = Objects.requireNonNullElse( transaction.getParentTransaction(), transaction);
 – 
Holger
18 Янв 2022 в 15:35
public void build(Transaction transaction) {
        final long amount = Optional.ofNullable(transaction.getParentTransaction()).orElse(transaction).getAmount();
        final String orderNumber = Optional.ofNullable(transaction.getParentTransaction()).orElse(transaction).getOrderNumber();
        // same pattern follows for more fields...


        // do other stuff...
    }

Здесь можно использовать Optional.ofNullable().orElse()

1
Krushil Dhamelia 18 Янв 2022 в 15:27

Используйте небольшой рефакторинг с необязательным:

public void build(Transaction transaction) {
    Transaction t = Optional.of(transaction).map(Transaction::getParent).orElse(transaction);
    long amount = t.getAmount(); 
    String orderNumber = t.getOrderNumber();
    // etc
}
1
Bohemian 18 Янв 2022 в 15:30
2
Если вам действительно не нравится (parent != null? parent: transaction), вы можете использовать Objects.requireNonNullElse(parent, transaction), по-прежнему не требуя Optional. И даже лучше, после Transaction toUse = Objects.requireNonNullElse(transaction.getParentTransaction(), transaction); следует использовать только toUse вместо повторения условного оператора снова и снова.
 – 
Holger
18 Янв 2022 в 15:29
2
Да, использование класса Objects намного лучше. Я бы рекомендовал не использовать Optional для таких простых условий, это антипаттерн, когда вы создаете лишний объект только для того, чтобы проверить его отсутствие или наличие. Просто используйте класс Objects или оператор if.
 – 
Tarun
18 Янв 2022 в 15:34
Мне нравится подход requireNonNullElse, но, к сожалению, он недоступен в Java 8.
 – 
Robert Strauch
18 Янв 2022 в 15:35
1
Вы можете легко создать свой собственный public static <T> T requireNonNullElse(T object, T fallback) { return object != null? object: fallback; } и использовать его, пока не перейдете на более позднюю версию Java и не переключитесь на реализацию JDK.
 – 
Holger
18 Янв 2022 в 15:38