Рефакторинг оператора if, где я должен инициализировать другой объект - PullRequest
0 голосов
/ 23 ноября 2018

Я ищу самый умный способ обработки этого метода

public boolean addAccount(String cf, AccountType type) {
    String iban = name + cf;
    if (bankAccounts.containsKey(iban)) return false;
    if (type.name().equals("CHECKINGACCOUNT")) {
        CheckingAccount cc = new CheckingAccount(cf, iban, 0);
        bankAccounts.put(iban, cc);
        return true;
    }
    if (type.name().equals("DEPOSIT")) {
        DepositAccount cd = new DepositAccount(cf, iban, 0);
        bankAccounts.put(iban, cd);
        return true;
    }
    if (type.name().equals("WEB")) {
        WebAccount cw = new WebAccount(cf, iban, 0);
        bankAccounts.put(iban, cw);
        return true;
    }
  return false;
}

AccountType - это enum, который содержит (DEPOSIT, WEB, CHECKINGACCOUNT);bankAccounts - это HashMap, содержащий iban (ключ) & CheckingAccounts OR DepositAccount OR WebAccount;CheckingAccounts, DepositAccount, WebAccount - это 3 класса, которые наследуют абстрактный класс с именем Account.

Я пытаюсь заменить if на HashMap, проверяющий ключ (Типaccount) со вставкой String пользователем и создает один из трех классов, связанных с ключом в HashMap.Проблема в том, что я не могу создать соответствие между Строкой и Учетной записью, потому что мне нужно создать экземпляр этого (но я не знаю cf в тот момент)

Может кто-нибудь показать мне лучший способсправиться?

Ответы [ 3 ]

0 голосов
/ 23 ноября 2018

Почему бы не поставить логику, для которой создание учетной записи, прямо в самом перечислении, используя фабричный шаблон?Начиная с Java 8, этот шаблон действительно гладкий, так как вы можете буквально передать конструктор как реализацию фабрики:

public boolean addAccount(String cf, AccountType type) {
    String iban = name + cf;
    if (bankAccounts.containsKey(iban)) return false;
    Account account = type.createAccount(cf, iban, 0);    
    bankAccounts.put(iban, account);
    return true;
}

public enum AccountType {
    CHECKING(CheckingAccount::new),
    DEPOSIT(DepositAccount::new),
    WEB(WebAccount::new);

    private final AccountFactory factory;
    AccountType(AccountFactory factory) {
        this.factory = factory;
    }

    public Account createAccount(String cf, String iban, int x) {
        return factory.create(cf, iban, x);
    }
}

public interface AccountFactory {
    Account create(String cf, String iban, int x);
}

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

0 голосов
/ 23 ноября 2018

Мое мнение таково, что концептуально все в порядке с этим методом.Я бы немного его изменил:

   public boolean addAccount(String cf, AccountType type) {
    String iban = name + cf;
    if (bankAccounts.containsKey(iban)) return false;

    Account ac;
    if (type == CHECKING) {
        ac = new CheckingAccount(cf, iban, 0);
    } else if (type == DEPOSIT) {
        ac = new DepositAccount(cf, iban, 0);
    } else if (type == WEB) {
        ac = new WebAccount(cf, iban, 0);
    }
    bankAccounts.put(iban, cc);
    return true;
}

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

0 голосов
/ 23 ноября 2018

Я бы не советовал использовать любую карту типов, так как она только увеличивает сложность и затраты времени выполнения.Заявление о переключении кажется самым простым.Вот пример:

public boolean addAccount(String cf, AccountType type) {
    String iban = name + cf;
    if (bankAccounts.containsKey(iban)) return false;
    Account account;
    switch(type) {
      case CHECKINGACCOUNT:
        account = new CheckingAccount(cf, iban, 0);
        break;
      case DEPOSIT:
        account = new DepositAccount(cf, iban, 0);
        break;
      case WEB:
        account = new WebAccount(cf, iban, 0);
        break;
      default:
         return false; 
   } 
   bankAccounts.put(iban, account);
   return true;
}

Однако, если вы решили использовать карту типов:

static Map<AccountType, Class> TYPE_MAP = new HashMap<>() 
{
   {AccountType.CHECKINGACCOUNT, CheckingAccount.class},
   {AccountType.DEPOSIT, DepositAccount.class},
   {AccountType.WEB, WebAccount.class}
};

public boolean addAccount(String cf, AccountType type) {
    String iban = name + cf;
    if (bankAccounts.containsKey(iban)) return false;
    if (!TYPE_MAP.containsKey(type)) return false;
    Class classType = TYPE_MAP.get(type);
    Account account = (Account)classType
      .getDeclaredConstructor(
        String.class,
        String.class,
        Integer.class)
      .newInstance(cf, iban, 0);
    bankAccounts.put(iban, account);
    return true;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...